段小段 1 年間 前
コミット
4cfd935636
100 ファイル変更3886 行追加0 行削除
  1. 14 0
      .editorconfig
  2. 31 0
      .env.development
  3. 13 0
      .env.production
  4. 8 0
      .env.staging
  5. 4 0
      .eslintignore
  6. 199 0
      .eslintrc.js
  7. 16 0
      .gitignore
  8. 5 0
      .travis.yml
  9. 1 0
      2020-02-19.txp
  10. 21 0
      LICENSE
  11. 96 0
      README-zh.md
  12. 148 0
      README.md
  13. 10 0
      babel.config.js
  14. 34 0
      build/index.js
  15. 127 0
      debug.log
  16. 24 0
      jest.config.js
  17. 116 0
      mock/article.js
  18. 69 0
      mock/index.js
  19. 112 0
      mock/menu.js
  20. 68 0
      mock/mock-server.js
  21. 29 0
      mock/table.js
  22. 86 0
      mock/user.js
  23. 89 0
      package.json
  24. 8 0
      postcss.config.js
  25. BIN
      public/favicon.ico
  26. 24 0
      public/index.html
  27. 11 0
      sh.exe.stackdump
  28. 139 0
      src/App.vue
  29. 41 0
      src/api/article.js
  30. 37 0
      src/api/chart.js
  31. 466 0
      src/api/common.js
  32. 73 0
      src/api/dashboard.js
  33. 49 0
      src/api/dept.js
  34. 22 0
      src/api/exeSql.js
  35. 11 0
      src/api/menu.js
  36. 17 0
      src/api/remote-search.js
  37. 54 0
      src/api/source.js
  38. 9 0
      src/api/table.js
  39. 24 0
      src/api/user.js
  40. BIN
      src/assets/404_images/404.png
  41. BIN
      src/assets/404_images/404_cloud.png
  42. BIN
      src/assets/cow.jpg
  43. BIN
      src/assets/custom-theme/fonts/element-icons.ttf
  44. 0 0
      src/assets/custom-theme/index.css
  45. 3 0
      src/assets/iconfont/iconfont.css
  46. BIN
      src/assets/iconfont/iconfont.eot
  47. 0 0
      src/assets/iconfont/iconfont.js
  48. 28 0
      src/assets/iconfont/iconfont.svg
  49. BIN
      src/assets/iconfont/iconfont.ttf
  50. BIN
      src/assets/iconfont/iconfont.woff
  51. BIN
      src/assets/iconfont/iconfont.woff2
  52. BIN
      src/assets/images/index/l1.png
  53. BIN
      src/assets/images/index/l2.png
  54. BIN
      src/assets/images/index/l3.png
  55. BIN
      src/assets/images/index/l4.png
  56. BIN
      src/assets/images/index/row-bg1.png
  57. BIN
      src/assets/images/index/row-bg2.png
  58. BIN
      src/assets/images/index/row-bg3.png
  59. BIN
      src/assets/images/index/row-l1.png
  60. BIN
      src/assets/images/index/row-l2.png
  61. BIN
      src/assets/images/index/row-r1.png
  62. BIN
      src/assets/images/index/row-r10.png
  63. BIN
      src/assets/images/index/row-r2.png
  64. BIN
      src/assets/images/index/row-r3.png
  65. BIN
      src/assets/images/index/row-r4.png
  66. BIN
      src/assets/images/index/row-r5.png
  67. BIN
      src/assets/images/index/row-r6.png
  68. BIN
      src/assets/images/index/row-r7.png
  69. BIN
      src/assets/images/index/row-r8.png
  70. BIN
      src/assets/images/index/row-r9.png
  71. BIN
      src/assets/images/index/t1.png
  72. BIN
      src/assets/images/index/t2.png
  73. BIN
      src/assets/images/index/t3.png
  74. BIN
      src/assets/images/index/t4.png
  75. BIN
      src/assets/images/index/topBg.png
  76. BIN
      src/assets/images/logo.png
  77. BIN
      src/assets/images/logo1.png
  78. BIN
      src/assets/images/logo_u3.png
  79. BIN
      src/assets/images/materiallssuancePlan/bg1.png
  80. BIN
      src/assets/images/nlogin-bg.png
  81. BIN
      src/assets/images/nlogin-bg1.jpg
  82. BIN
      src/assets/images/nlogin-bg2.png
  83. BIN
      src/assets/images/nlogin-bg3.png
  84. BIN
      src/assets/images/nlogo1.png
  85. BIN
      src/assets/images/nlogo2.png
  86. BIN
      src/assets/images/sanjiao.png
  87. 117 0
      src/componentChart/BarChart.vue
  88. 185 0
      src/componentChart/ChartTable.vue
  89. 121 0
      src/componentChart/HorizontalBarChart.vue
  90. 135 0
      src/componentChart/LineBarChart.vue
  91. 118 0
      src/componentChart/LineChart.vue
  92. 138 0
      src/componentChart/PieChart.vue
  93. 79 0
      src/components/Breadcrumb/index.vue
  94. 141 0
      src/components/ChartTable.vue
  95. 99 0
      src/components/Encapsulation/index.vue
  96. 54 0
      src/components/GithubCorner/index.vue
  97. 45 0
      src/components/Hamburger/index.vue
  98. 180 0
      src/components/HeaderSearch/index.vue
  99. 35 0
      src/components/InputGroup/index.vue
  100. 103 0
      src/components/Pagination/index.vue

+ 14 - 0
.editorconfig

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

+ 31 - 0
.env.development

@@ -0,0 +1,31 @@
+# just a flag
+ENV = 'development'
+
+# base api
+# 测试线
+# VUE_APP_BASE_API = 'http://210.16.189.72:8081/'
+
+
+# VUE_APP_BASE_API = 'http://kpttest.kptyun.com/'
+
+
+
+# VUE_APP_BASE_API = 'http://tmrwatch.cn:8081/'
+
+
+
+# VUE_APP_BASE_API = 'http://lhpc81.kptyun.com/'
+
+
+#许义平本地
+VUE_APP_BASE_API = 'http://192.168.1.96:8000/'
+
+#=====
+# vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
+# to control whether the babel-plugin-dynamic-import-node plugin is enabled.
+# It only does one thing by converting all import() to require().
+# This configuration can significantly increase the speed of hot updates,
+# when you have a large number of pages.
+# Detail:  https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/babel-preset-app/index.js
+
+VUE_CLI_BABEL_TRANSPILE_MODULES = true

+ 13 - 0
.env.production

@@ -0,0 +1,13 @@
+# just a flag
+ENV = 'production'
+
+# base api
+# 正式线
+# VUE_APP_BASE_API = ':8081/'
+VUE_APP_BASE_API = '/'
+# 测试线
+# VUE_APP_BASE_API = 'http://210.16.189.72:8081/'
+#洋洋本地
+# VUE_APP_BASE_API = 'http://192.168.1.104:8081/'
+#本地
+# VUE_APP_BASE_API = 'http://192.168.1.55:8084/'

+ 8 - 0
.env.staging

@@ -0,0 +1,8 @@
+NODE_ENV = production
+
+# just a flag
+ENV = 'staging'
+
+# base api
+VUE_APP_BASE_API = '/stage-api'
+

+ 4 - 0
.eslintignore

@@ -0,0 +1,4 @@
+build/*.js
+src/assets
+public
+dist

+ 199 - 0
.eslintrc.js

@@ -0,0 +1,199 @@
+module.exports = {
+  root: true,
+  parserOptions: {
+    parser: 'babel-eslint',
+    parser: '@babel/eslint-parser',
+    sourceType: 'module'
+  },
+  env: {
+    browser: true,
+    node: true,
+    es6: true,
+  },
+  extends: ['plugin:vue/recommended', 'eslint:recommended'],
+
+  // add your custom rules here
+  //it is base on https://github.com/vuejs/eslint-config-vue
+  rules: {
+    "vue/max-attributes-per-line": [2, {
+      "singleline": 10,
+      "multiline": {
+        "max": 1,
+        "allowFirstLine": false
+      }
+    }],
+    "vue/singleline-html-element-content-newline": "off",
+    "vue/multiline-html-element-content-newline":"off",
+    "vue/name-property-casing": ["error", "PascalCase"],
+    "vue/no-v-html": "off",
+    'accessor-pairs': 2,
+    'arrow-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'block-spacing': [2, 'always'],
+    'brace-style': [2, '1tbs', {
+      'allowSingleLine': true
+    }],
+    'camelcase': [0, {
+      'properties': 'always'
+    }],
+    'comma-dangle': [2, 'never'],
+    'comma-spacing': [2, {
+      'before': false,
+      'after': true
+    }],
+    'comma-style': [2, 'last'],
+    'constructor-super': 2,
+    'curly': [2, 'multi-line'],
+    'dot-location': [2, 'property'],
+    'eol-last': 2,
+    'eqeqeq': ["error", "always", {"null": "ignore"}],
+    'generator-star-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'handle-callback-err': [2, '^(err|error)$'],
+    'indent': [2, 2, {
+      'SwitchCase': 1
+    }],
+    'jsx-quotes': [2, 'prefer-single'],
+    'key-spacing': [2, {
+      'beforeColon': false,
+      'afterColon': true
+    }],
+    'keyword-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'new-cap': [2, {
+      'newIsCap': true,
+      'capIsNew': false
+    }],
+    'new-parens': 2,
+    'no-array-constructor': 2,
+    'no-caller': 2,
+    'no-console': 'off',
+    'no-class-assign': 2,
+    'no-cond-assign': 2,
+    'no-const-assign': 2,
+    'no-control-regex': 0,
+    'no-delete-var': 2,
+    'no-dupe-args': 2,
+    'no-dupe-class-members': 2,
+    'no-dupe-keys': 2,
+    'no-duplicate-case': 2,
+    'no-empty-character-class': 2,
+    'no-empty-pattern': 2,
+    'no-eval': 2,
+    'no-ex-assign': 2,
+    'no-extend-native': 2,
+    'no-extra-bind': 2,
+    'no-extra-boolean-cast': 2,
+    'no-extra-parens': [2, 'functions'],
+    'no-fallthrough': 2,
+    'no-floating-decimal': 2,
+    'no-func-assign': 2,
+    'no-implied-eval': 2,
+    'no-inner-declarations': [2, 'functions'],
+    'no-invalid-regexp': 2,
+    'no-irregular-whitespace': 2,
+    'no-iterator': 2,
+    'no-label-var': 2,
+    'no-labels': [2, {
+      'allowLoop': false,
+      'allowSwitch': false
+    }],
+    'no-lone-blocks': 2,
+    'no-mixed-spaces-and-tabs': 2,
+    'no-multi-spaces': 2,
+    'no-multi-str': 2,
+    'no-multiple-empty-lines': [2, {
+      'max': 1
+    }],
+    'no-native-reassign': 2,
+    'no-negated-in-lhs': 2,
+    'no-new-object': 2,
+    'no-new-require': 2,
+    'no-new-symbol': 2,
+    'no-new-wrappers': 2,
+    'no-obj-calls': 2,
+    'no-octal': 2,
+    'no-octal-escape': 2,
+    'no-path-concat': 2,
+    'no-proto': 2,
+    'no-redeclare': 2,
+    'no-regex-spaces': 2,
+    'no-return-assign': [2, 'except-parens'],
+    'no-self-assign': 2,
+    'no-self-compare': 2,
+    'no-sequences': 2,
+    'no-shadow-restricted-names': 2,
+    'no-spaced-func': 2,
+    'no-sparse-arrays': 2,
+    'no-this-before-super': 2,
+    'no-throw-literal': 2,
+    'no-trailing-spaces': 2,
+    'no-undef': 2,
+    'no-undef-init': 2,
+    'no-unexpected-multiline': 2,
+    'no-unmodified-loop-condition': 2,
+    'no-unneeded-ternary': [2, {
+      'defaultAssignment': false
+    }],
+    'no-unreachable': 2,
+    'no-unsafe-finally': 2,
+    'no-unused-vars': [2, {
+      'vars': 'all',
+      'args': 'none'
+    }],
+    'no-useless-call': 2,
+    'no-useless-computed-key': 2,
+    'no-useless-constructor': 2,
+    'no-useless-escape': 0,
+    'no-whitespace-before-property': 2,
+    'no-with': 2,
+    'one-var': [2, {
+      'initialized': 'never'
+    }],
+    'operator-linebreak': [2, 'after', {
+      'overrides': {
+        '?': 'before',
+        ':': 'before'
+      }
+    }],
+    'padded-blocks': [2, 'never'],
+    'quotes': [2, 'single', {
+      'avoidEscape': true,
+      'allowTemplateLiterals': true
+    }],
+    'semi': [2, 'never'],
+    'semi-spacing': [2, {
+      'before': false,
+      'after': true
+    }],
+    'space-before-blocks': [2, 'always'],
+    'space-before-function-paren': [2, 'never'],
+    'space-in-parens': [2, 'never'],
+    'space-infix-ops': 2,
+    'space-unary-ops': [2, {
+      'words': true,
+      'nonwords': false
+    }],
+    'spaced-comment': [2, 'always', {
+      'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
+    }],
+    'template-curly-spacing': [2, 'never'],
+    'use-isnan': 2,
+    'valid-typeof': 2,
+    'wrap-iife': [2, 'any'],
+    'yield-star-spacing': [2, 'both'],
+    'yoda': [2, 'never'],
+    'prefer-const': 2,
+    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
+    'object-curly-spacing': [2, 'always', {
+      objectsInObjects: false
+    }],
+    'array-bracket-spacing': [2, 'never']
+  }
+}

+ 16 - 0
.gitignore

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

+ 5 - 0
.travis.yml

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

ファイルの差分が大きいため隠しています
+ 1 - 0
2020-02-19.txp


+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017-present PanJiaChen
+
+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.

+ 96 - 0
README-zh.md

@@ -0,0 +1,96 @@
+# vue-admin-template
+
+> 这是一个极简的 vue admin 管理后台。它只包含了 Element UI & axios & iconfont & permission control & lint,这些搭建后台必要的东西。
+
+[线上地址](http://panjiachen.github.io/vue-admin-template)
+
+[国内访问](https://panjiachen.gitee.io/vue-admin-template)
+
+目前版本为 `v4.0+` 基于 `vue-cli` 进行构建,若你想使用旧版本,可以切换分支到[tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0),它不依赖 `vue-cli`。
+
+## Extra
+
+如果你想要根据用户角色来动态生成侧边栏和 router,你可以使用该分支[permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)
+
+## 相关项目
+
+[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
+
+[electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
+
+[vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template)
+
+写了一个系列的教程配套文章,如何从零构建后一个完整的后台项目:
+
+- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
+- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
+- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
+- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板,专门针对本项目的文章,算作是一篇文档)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
+- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
+
+## Build Setup
+
+```bash
+# 克隆项目
+git clone https://github.com/PanJiaChen/vue-admin-template.git
+
+# 进入项目目录
+cd vue-admin-template
+
+# 安装依赖
+npm install
+
+# 建议不要直接使用 cnpm 安装以来,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
+npm install --registry=https://registry.npm.taobao.org
+
+# 启动服务
+npm run dev
+```
+
+浏览器访问 [http://localhost:9528](http://localhost:9528)
+
+## 发布
+
+```bash
+# 构建测试环境
+npm run build:stage
+
+# 构建生产环境
+npm run build:prod
+```
+
+## 其它
+
+```bash
+# 预览发布环境效果
+npm run preview
+
+# 预览发布环境效果 + 静态资源分析
+npm run preview -- --report
+
+# 代码格式检查
+npm run lint
+
+# 代码格式检查并自动修复
+npm run lint -- --fix
+```
+
+更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
+
+## Demo
+
+![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif)
+
+## Browsers support
+
+Modern browsers and Internet Explorer 10+.
+
+| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
+| --------- | --------- | --------- | --------- |
+| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
+
+## License
+
+[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license.
+
+Copyright (c) 2017-present PanJiaChen

+ 148 - 0
README.md

@@ -0,0 +1,148 @@
+# vue-admin-template
+
+English | [简体中文](./README-zh.md)
+
+> A minimal vue admin template with Element UI & axios & iconfont & permission control & lint
+
+**Live demo:** http://panjiachen.github.io/vue-admin-template
+
+
+**The current version is `v4.0+` build on `vue-cli`. If you want to use the old version , you can switch branch to [tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0), it does not rely on `vue-cli`**
+
+## Build Setup
+
+
+```bash
+# clone the project
+git clone https://github.com/PanJiaChen/vue-admin-template.git
+
+# enter the project directory
+cd vue-admin-template
+
+# install dependency
+npm install
+
+# develop
+npm run dev
+```
+
+This will automatically open http://localhost:9528
+
+## Build
+
+```bash
+# build for test environment
+npm run build:stage
+
+# build for production environment
+npm run build:prod
+```
+
+## Advanced
+
+```bash
+# preview the release environment effect
+npm run preview
+
+# preview the release environment effect + static resource analysis
+npm run preview -- --report
+
+# code format check
+npm run lint
+
+# code format check and auto fix
+npm run lint -- --fix
+```
+
+Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information
+
+## Demo
+
+![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif)
+
+## Extra
+
+If you want router permission && generate menu by user roles , you can use this branch [permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)
+
+For `typescript` version, you can use [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
+
+## Related Project
+
+[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
+
+[electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
+
+[vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template)
+
+## Browsers support
+
+Modern browsers and Internet Explorer 10+.
+
+| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
+| --------- | --------- | --------- | --------- |
+| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
+
+## License
+
+[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license.
+
+Copyright (c) 2017-present PanJiaChen
+
+
+
+1.	统计分析			  statisticalAnalysis
+1-1.实时监控		    realTimeMonitoring
+1-2.过程分析		    processAnalysis
+1-3.误差分析		    errorAnalysis
+1-4.用料分析		    materialAnalysis
+1-5.价格分析		    priceAnalysis
+1-6.效率分析		    efficiencyAnalysis
+1-7.效率统计		    efficiencyStatistics
+
+2.  统计图表      statisticalChart
+2-1.配方统计      formulaStatistics
+2-2.栏舍统计      shedStatistics
+
+3.  配方计划      formulationPlan
+3-1.配方模板      recipeTemplate
+3-2.栏舍配方      dhedFormula
+3-3.预混计划      premixedPlan
+3-4.发料计划      materialIssuancePlan
+3-5.剩料计划      surplusMaterialPlan
+3-6.日执行计划    dailyExecutionPlan
+
+4.栏舍生产        shedProduction
+4-1.栏舍生产性能  performance
+4-2.栏舍剩料记录  materialRemainingRecord
+4-3.配方干物质    formulaDryMatter
+4-4.配方价格      formulaPrice
+4-5.宾州筛        pennsylvaniaSieve
+4-6.粪便筛        fecalScreen
+4-7.粪便评分      dungScores
+4-8.体况评分      physicalConditionScore
+
+5.库存管理        inventoryManagement
+5-1.入库管理      warehousing
+5-2.系统用量      systemConsumption
+5-3.人工用量      laborConsumption
+5-4.盘点单        inventoryList
+5-5.库存预警      warning
+5-6.库存统计      statistics
+
+6.基础数据        basicData
+6-1.驾驶员        driver
+6-2.TMR设备       equipmentTMR
+6-3.铲车管理      forkliftManagement
+6-4.牲畜类别      livestockCategory
+6-5.舍组栏      	 groupColumn
+6-6.饲料分类      feedClassification
+6-7.饲料表        feedTable
+6-8.标准参数      standardParameters
+6-9.默认参数配置  defaultParameter
+
+7.系统管理        	systemManagement
+7-1.集团信息		 	groupInformation
+7-2.牧场信息		 	ranchInformation
+7-3.角色管理			role
+7-4.用户管理			user
+7-5.操作日志(审计)	operation 

+ 10 - 0
babel.config.js

@@ -0,0 +1,10 @@
+const prodPlugins=[]
+if(process.env.NODE_ENV === 'production'){
+  prodPlugins.push("transform-remove-console")
+}
+module.exports = {
+  presets: [
+    '@vue/app'
+  ],
+  plugins: [...prodPlugins]
+}

+ 34 - 0
build/index.js

@@ -0,0 +1,34 @@
+const { run } = require('runjs')
+const chalk = require('chalk')
+const config = require('../vue.config.js')
+const rawArgv = process.argv.slice(2)
+const args = rawArgv.join(' ')
+
+if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
+  const report = rawArgv.includes('--report')
+
+  run(`vue-cli-service build ${args}`)
+
+  const port = 9526
+  const publicPath = config.publicPath
+
+  var connect = require('connect')
+  var serveStatic = require('serve-static')
+  const app = connect()
+
+  app.use(
+    publicPath,
+    serveStatic('./dist', {
+      index: ['index.html', '/']
+    })
+  )
+  app.listen(port, function () {
+    console.log(chalk.green(`> Preview at  http://localhost:${port}${publicPath}`))
+    if (report) {
+      console.log(chalk.green(`> Report at  http://localhost:${port}${publicPath}report.html`))
+    }
+
+  })
+} else {
+  run(`vue-cli-service build ${args}`)
+}

+ 127 - 0
debug.log

@@ -0,0 +1,127 @@
+[0317/174929.466:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0320/173441.003:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0324/171832.361:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0326/114532.451:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0326/174029.035:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0330/102225.637:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0330/160524.844:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0331/180453.024:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0401/162157.520:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0402/165808.951:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0403/112343.031:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0403/134118.452:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0407/113651.340:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0407/180252.092:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0408/150218.094:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0410/104721.642:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0410/155916.867:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0413/145754.944:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0414/141831.460:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0414/154438.334:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0415/153518.201:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0416/112338.997:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0416/161655.335:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0417/141409.629:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0422/155012.381:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0428/175551.742:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0507/161117.954:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0509/181813.959:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0511/155936.922:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0515/155928.607:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0520/145310.286:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0601/113705.004:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0605/140648.507:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0616/160221.674:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0619/111927.316:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0622/133635.922:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0623/161920.161:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0628/142402.809:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0628/171924.492:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0710/131804.495:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0728/124804.485:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0817/134320.441:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0819/104154.277:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0823/120710.795:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0824/180735.938:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0826/172528.094:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0831/151716.494:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0901/170522.063:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0902/160013.710:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0912/165925.942:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0918/164433.625:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0919/165440.003:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0922/154859.740:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0927/141632.107:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[1012/091710.150:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1013/091344.955:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1014/091131.373:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1015/090408.932:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1016/091326.378:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1019/092042.958:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1019/092043.038:ERROR:filesystem_win.cc(129)] GetFileAttributes C:\Users\zjh\AppData\Local\Google\Chrome\User Data\Crashpad\attachments\29196c32-487a-42cb-8985-eef0cd54a40b: 系统找不到指定的路径。 (0x3)
+[1019/150921.712:ERROR:filesystem_win.cc(129)] GetFileAttributes C:\Users\zjh\AppData\Local\Google\Chrome\User Data\Crashpad\attachments\1f83b1c0-d72b-41fc-aff0-a4601b881674: 系统找不到指定的路径。 (0x3)
+[1019/150942.726:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[1106/091032.637:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1110/092128.018:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1111/092331.618:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1111/092331.681:ERROR:filesystem_win.cc(129)] GetFileAttributes C:\Users\zjh\AppData\Local\Google\Chrome\User Data\Crashpad\attachments\5c73a72a-ba36-469e-9e09-aeb576cc22cb: 系统找不到指定的路径。 (0x3)
+[1112/092111.582:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1112/092111.640:ERROR:filesystem_win.cc(129)] GetFileAttributes C:\Users\zjh\AppData\Local\Google\Chrome\User Data\Crashpad\attachments\76fa7128-32fe-47bc-88ff-1fcdaec2cef2: 系统找不到指定的路径。 (0x3)
+[1113/092903.257:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1116/092304.862:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1117/092211.934:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1117/135357.303:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1118/092040.281:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1119/091823.721:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1120/091938.326:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1122/092520.877:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1123/091904.724:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1125/091833.812:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1125/174946.677:ERROR:filesystem_win.cc(129)] GetFileAttributes C:\Users\zjh\AppData\Local\Google\Chrome\User Data\Crashpad\attachments\63f001d1-a8ce-4513-93fe-c72a7b1a4900: 系统找不到指定的路径。 (0x3)
+[1125/175007.909:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[1126/092127.473:ERROR:filesystem_win.cc(129)] GetFileAttributes C:\Users\zjh\AppData\Local\Google\Chrome\User Data\Crashpad\attachments\b71102cc-a231-426f-a419-97f8cee61d1e: 系统找不到指定的路径。 (0x3)
+[1126/092148.591:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[1127/093003.148:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1128/100233.905:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1128/103003.744:ERROR:file_io.cc(90)] ReadExactly: expected 36, observed 0
+[1130/092211.375:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1130/094336.319:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1201/092726.969:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1201/130719.326:ERROR:filesystem_win.cc(129)] GetFileAttributes C:\Users\zjh\AppData\Local\Google\Chrome\User Data\Crashpad\attachments\72e1eaa9-aaeb-4e5c-8c0b-fc560b1e5fd5: 系统找不到指定的路径。 (0x3)
+[1201/130740.407:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[1201/152435.323:ERROR:filesystem_win.cc(129)] GetFileAttributes C:\Users\zjh\AppData\Local\Google\Chrome\User Data\Crashpad\attachments\1406e09a-7f92-4e85-9943-c50f6cbf7bd1: 系统找不到指定的路径。 (0x3)
+[1201/152456.399:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[1201/163544.754:ERROR:filesystem_win.cc(129)] GetFileAttributes C:\Users\zjh\AppData\Local\Google\Chrome\User Data\Crashpad\attachments\aa004f6a-20d5-4656-8cb2-730f2aecf0ef: 系统找不到指定的路径。 (0x3)
+[1201/163605.848:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[1202/091405.612:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1203/091848.325:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1207/092038.129:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1207/171907.289:ERROR:filesystem_win.cc(129)] GetFileAttributes C:\Users\zjh\AppData\Local\Google\Chrome\User Data\Crashpad\attachments\b659a819-a08a-48d5-9a7c-5ed16a8dc0be: 系统找不到指定的路径。 (0x3)
+[1207/171928.432:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[1208/091816.984:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1209/092427.504:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1225/093026.628:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1228/092441.898:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[1228/092441.994:ERROR:filesystem_win.cc(129)] GetFileAttributes C:\Users\zjh\AppData\Local\Google\Chrome\User Data\Crashpad\attachments\34a147bd-bada-4ecf-a152-2cd961b81a51: 系统找不到指定的路径。 (0x3)
+[1229/091654.602:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0104/092557.894:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0106/091912.923:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0107/091858.228:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0108/092138.942:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0111/092635.535:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0112/092412.232:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0113/091855.633:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0114/091918.336:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0114/161940.939:ERROR:filesystem_win.cc(129)] GetFileAttributes C:\Users\zjh\AppData\Local\Google\Chrome\User Data\Crashpad\attachments\02d37f2c-2ff6-411a-b1e4-de29059e6015: 系统找不到指定的路径。 (0x3)
+[0114/162001.257:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0115/091811.027:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0117/103033.402:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0118/092101.772:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0119/092024.071:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0123/093355.023:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0125/091851.087:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0125/151904.089:ERROR:filesystem_win.cc(129)] GetFileAttributes C:\Users\zjh\AppData\Local\Google\Chrome\User Data\Crashpad\attachments\b65df76b-967c-4960-9f9f-031604d3e18d: 系统找不到指定的路径。 (0x3)
+[0125/152110.418:ERROR:http_transport_win.cc(276)] WinHttpSendRequest: 操作成功完成。 (0x0)
+[0126/091847.364:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0127/091036.118:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)
+[0128/092334.873:ERROR:directory_reader_win.cc(43)] FindFirstFile: 系统找不到指定的路径。 (0x3)

+ 24 - 0
jest.config.js

@@ -0,0 +1,24 @@
+module.exports = {
+  moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
+  transform: {
+    '^.+\\.vue$': 'vue-jest',
+    '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
+      'jest-transform-stub',
+    '^.+\\.jsx?$': 'babel-jest'
+  },
+  moduleNameMapper: {
+    '^@/(.*)$': '<rootDir>/src/$1'
+  },
+  snapshotSerializers: ['jest-serializer-vue'],
+  testMatch: [
+    '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
+  ],
+  collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
+  coverageDirectory: '<rootDir>/tests/unit/coverage',
+  // 'collectCoverage': true,
+  'coverageReporters': [
+    'lcov',
+    'text-summary'
+  ],
+  testURL: 'http://localhost/'
+}

+ 116 - 0
mock/article.js

@@ -0,0 +1,116 @@
+import Mock from 'mockjs'
+
+const List = []
+const count = 100
+
+const baseContent = '<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>'
+const image_uri = 'https://wpimg.wallstcn.com/e4558086-631c-425c-9430-56ffb46e70b3'
+
+for (let i = 0; i < count; i++) {
+  List.push(Mock.mock({
+    id: '@increment',
+    timestamp: +Mock.Random.date('T'),
+    author: '@first',
+    reviewer: '@first',
+    title: '@title(5, 10)',
+    content_short: 'mock data',
+    content: baseContent,
+    forecast: '@float(0, 100, 2, 2)',
+    importance: '@integer(1, 3)',
+    'type|1': ['CN', 'US', 'JP', 'EU'],
+    'status|1': ['发布', '草稿', '已删'],
+    display_time: '@datetime',
+    comment_disabled: true,
+    pageviews: '@integer(300, 5000)',
+    image_uri,
+    platforms: ['a-platform']
+  }))
+}
+
+export default [
+  {
+    url: '/article/list',
+    type: 'get',
+    response: config => {
+      const { importance, type, title, page = 1, limit = 20, sort } = config.query
+
+      let mockList = List.filter(item => {
+        if (importance && item.importance !== +importance) return false
+        if (type && item.type !== type) return false
+        if (title && item.title.indexOf(title) < 0) return false
+        return true
+      })
+
+      if (sort === '-id') {
+        mockList = mockList.reverse()
+      }
+
+      const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1))
+
+      return {
+        code: 200,
+        data: {
+          total: mockList.length,
+          items: pageList
+        }
+      }
+    }
+  },
+
+  {
+    url: '/article/detail',
+    type: 'get',
+    response: config => {
+      const { id } = config.query
+      for (const article of List) {
+        if (article.id === +id) {
+          return {
+            code: 200,
+            data: article
+          }
+        }
+      }
+    }
+  },
+
+  {
+    url: '/article/pv',
+    type: 'get',
+    response: _ => {
+      return {
+        code: 200,
+        data: {
+          pvData: [
+            { key: 'PC', pv: 1024 },
+            { key: 'mobile', pv: 1024 },
+            { key: 'ios', pv: 1024 },
+            { key: 'android', pv: 1024 }
+          ]
+        }
+      }
+    }
+  },
+
+  {
+    url: '/article/create',
+    type: 'post',
+    response: _ => {
+      return {
+        code: 200,
+        data: 'success'
+      }
+    }
+  },
+
+  {
+    url: '/article/update',
+    type: 'post',
+    response: _ => {
+      return {
+        code: 200,
+        data: 'success'
+      }
+    }
+  }
+]
+

+ 69 - 0
mock/index.js

@@ -0,0 +1,69 @@
+import Mock from 'mockjs'
+import { param2Obj } from '../src/utils'
+
+import user from './user'
+import table from './table'
+import menuAPI from './menu'
+import article from './article'
+const mocks = [
+  ...user,
+  ...table,
+  ...menuAPI,
+  ...article
+]
+
+mockXHR// for front mock
+// please use it cautiously, it will redefine XMLHttpRequest,
+// which will cause many of your third-party libraries to be invalidated(like progress event).
+export function mockXHR() {
+  // mock patch
+  // https://github.com/nuysoft/Mock/issues/300
+  Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
+  Mock.XHR.prototype.send = function() {
+    if (this.custom.xhr) {
+      this.custom.xhr.withCredentials = this.withCredentials || false
+
+      if (this.responseType) {
+        this.custom.xhr.responseType = this.responseType
+      }
+    }
+    this.proxy_send(...arguments)
+  }
+
+  function XHR2ExpressReqWrap(respond) {
+    return function(options) {
+      let result = null
+      if (respond instanceof Function) {
+        const { body, type, url } = options
+        // https://expressjs.com/en/4x/api.html#req
+        result = respond({
+          method: type,
+          body: JSON.parse(body),
+          query: param2Obj(url)
+        })
+      } else {
+        result = respond
+      }
+      return Mock.mock(result)
+    }
+  }
+
+  for (const i of mocks) {
+    Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
+  }
+}
+
+// for mock server
+const responseFake = (url, type, respond) => {
+  return {
+    url: new RegExp(`/mock${url}`),
+    type: type || 'get',
+    response(req, res) {
+      res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
+    }
+  }
+}
+
+export default mocks.map(route => {
+  return responseFake(route.url, route.type, route.response)
+})

+ 112 - 0
mock/menu.js

@@ -0,0 +1,112 @@
+const menuData =
+[
+  {
+    'id': 1,
+    'path': '/console',
+    'redirect': 'noredirect',
+    'component': 'Layout',
+    'name': 'console',
+    'title': '系统管理',
+    'icon': 'form',
+    'parentId': -1,
+    'children': [
+      {
+        'children': [],
+        'id': 7,
+        'name': 'user',
+        'component': 'console/user/index',
+        'title': '用户管理',
+        'icon': 'user',
+        'parentId': 1,
+        'path': 'user'
+      },
+      {
+        'children': [],
+        'name': 'menu',
+        'component': 'console/menu/index',
+        'id': 8,
+        'title': '菜单管理',
+        'icon': 'table',
+        'parentId': 1,
+        'path': 'menu'
+      },
+      {
+        'children': [],
+        'name': 'role',
+        'component': 'console/role/index',
+        'id': 9,
+        'title': '角色管理',
+        'icon': 'table',
+        'parentId': 1,
+        'path': 'role'
+      },
+      {
+        'children': [],
+        'name': 'dict',
+        'component': 'console/dict/index',
+        'id': 10,
+        'title': '字典管理',
+        'icon': 'table',
+        'parentId': 1,
+        'path': 'dict'
+      },
+      {
+        'children': [],
+        'name': 'dept',
+        'component': 'console/dept/index',
+        'id': 11,
+        'title': '部门管理',
+        'icon': 'table',
+        'parentId': 1,
+        'path': 'dept'
+      }
+    ]
+  },
+  {
+    'id': 22,
+    'name': 'myiframe',
+    'component': 'Iframe',
+    'redirect': 'noredirect',
+    'title': '第三方系统',
+    'icon': 'link',
+    'path': '/myiframe',
+    'parentId': -1,
+    'children': [
+      {
+        'id': 23,
+        'children': [],
+        'name': 'wechat',
+        'component': 'Iframe',
+        'title': '微信',
+        'icon': 'wechat',
+        'parentId': 22,
+        'path': 'wechatUrl?src=https://pc.weixin.qq.com/&name=微信'
+      },
+      {
+        'id': 24,
+        'children': [],
+        'name': 'qq',
+        'component': 'Iframe',
+        'title': '腾讯QQ',
+        'icon': 'qq',
+        'parentId': 22,
+        'path': 'qqUrl?src=https://im.qq.com/index.shtml&name=腾讯QQ'
+      }
+    ]
+  }
+
+]
+
+export default [
+  {
+    url: '/authdata/rolemenus',
+    type: 'get',
+    response: _ => {
+      return {
+        code: 200,
+        data: menuData
+        // console.log(menuData)
+      }
+    }
+  }
+]

+ 68 - 0
mock/mock-server.js

@@ -0,0 +1,68 @@
+const chokidar = require('chokidar')
+const bodyParser = require('body-parser')
+const chalk = require('chalk')
+const path = require('path')
+
+const mockDir = path.join(process.cwd(), 'mock')
+
+function registerRoutes(app) {
+  let mockLastIndex
+  const { default: mocks } = require('./index.js')
+  for (const mock of mocks) {
+    app[mock.type](mock.url, mock.response)
+    mockLastIndex = app._router.stack.length
+  }
+  const mockRoutesLength = Object.keys(mocks).length
+  return {
+    mockRoutesLength: mockRoutesLength,
+    mockStartIndex: mockLastIndex - mockRoutesLength
+  }
+}
+
+function unregisterRoutes() {
+  Object.keys(require.cache).forEach(i => {
+    if (i.includes(mockDir)) {
+      delete require.cache[require.resolve(i)]
+    }
+  })
+}
+
+module.exports = app => {
+  // es6 polyfill
+  require('@babel/register')
+
+  // parse app.body
+  // https://expressjs.com/en/4x/api.html#req.body
+  app.use(bodyParser.json())
+  app.use(bodyParser.urlencoded({
+    extended: true
+  }))
+
+  const mockRoutes = registerRoutes(app)
+  var mockRoutesLength = mockRoutes.mockRoutesLength
+  var mockStartIndex = mockRoutes.mockStartIndex
+
+  // watch files, hot reload mock server
+  chokidar.watch(mockDir, {
+    ignored: /mock-server/,
+    ignoreInitial: true
+  }).on('all', (event, path) => {
+    if (event === 'change' || event === 'add') {
+      try {
+        // remove mock routes stack
+        app._router.stack.splice(mockStartIndex, mockRoutesLength)
+
+        // clear routes cache
+        unregisterRoutes()
+
+        const mockRoutes = registerRoutes(app)
+        mockRoutesLength = mockRoutes.mockRoutesLength
+        mockStartIndex = mockRoutes.mockStartIndex
+
+        console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed  ${path}`))
+      } catch (error) {
+        console.log(chalk.redBright(error))
+      }
+    }
+  })
+}

+ 29 - 0
mock/table.js

@@ -0,0 +1,29 @@
+import Mock from 'mockjs'
+
+const data = Mock.mock({
+  'items|30': [{
+    id: '@id',
+    title: '@sentence(10, 20)',
+    'status|1': ['published', 'draft', 'deleted'],
+    author: 'name',
+    display_time: '@datetime',
+    pageviews: '@integer(300, 5000)'
+  }]
+})
+
+export default [
+  {
+    url: '/table/list',
+    type: 'get',
+    response: config => {
+      const items = data.items
+      return {
+        code: 20000,
+        data: {
+          total: items.length,
+          items: items
+        }
+      }
+    }
+  }
+]

+ 86 - 0
mock/user.js

@@ -0,0 +1,86 @@
+
+const tokens = {
+  admin: {
+    token: 'admin-token'
+  },
+  editor: {
+    token: 'editor-token'
+  }
+}
+
+const users = {
+  'admin-token': {
+    role: ['admin'],
+    introduction: 'I am a super administrator',
+    avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
+    name: 'Super Admin'
+  },
+  'editor-token': {
+    role: ['editor'],
+    introduction: 'I am an editor',
+    avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
+    name: 'Normal Editor'
+  }
+}
+
+export default [
+  // user login
+  {
+    url: '/auth',
+    type: 'post',
+    response: config => {
+      const { username } = config.body
+      const token = tokens[username]
+
+      // mock error
+      if (!token) {
+        return {
+          code: 60204,
+          message: 'Account and password are incorrect.'
+        }
+      }
+
+      return {
+        code: 200,
+        data: token
+      }
+    }
+  },
+
+  // get user info
+  {
+    url: '/authdata/userinfo\.*',
+    type: 'get',
+    response: config => {
+      console.log(config)
+      let { token } = config.query
+      token = 'admin-token'
+      const info = users[token]
+
+      // mock error
+      if (!info) {
+        return {
+          code: 50008,
+          message: 'Login failed, unable to get user details.'
+        }
+      }
+
+      return {
+        code: 200,
+        data: info
+      }
+    }
+  },
+
+  // user logout
+  {
+    url: '/authdata/logout',
+    type: 'post',
+    response: _ => {
+      return {
+        code: 200,
+        data: 'success'
+      }
+    }
+  }
+]

+ 89 - 0
package.json

@@ -0,0 +1,89 @@
+{
+  "name": "vue-admin-template",
+  "version": "4.2.1",
+  "description": "A vue admin template with Element UI & axios & iconfont & permission control & lint",
+  "author": "Pan <panfree23@gmail.com>",
+  "license": "MIT",
+  "scripts": {
+    "dev": "vue-cli-service serve",
+    "build:prod": "vue-cli-service build",
+    "build:stage": "vue-cli-service build --mode staging",
+    "preview": "node build/index.js --preview",
+    "lint": "eslint --ext .js,.vue src",
+    "test:unit": "jest --clearCache && vue-cli-service test:unit",
+    "test:ci": "npm run lint && npm run test:unit",
+    "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
+  },
+  "dependencies": {
+    "@sentry/browser": "^5.15.5",
+    "@sentry/integrations": "^5.15.5",
+    "axios": "0.18.1",
+    "core-js": "^3.6.4",
+    "driver.js": "^0.9.6",
+    "echarts": "^5.4.2",
+    "element-ui": "^2.13.2",
+    "file-saver": "^2.0.5",
+    "fuse.js": "3.4.4",
+    "js-cookie": "^2.2.0",
+    "js-table2excel": "^1.0.3",
+    "md5": "^2.3.0",
+    "moment": "^2.24.0",
+    "normalize.css": "7.0.0",
+    "nprogress": "0.2.0",
+    "path-to-regexp": "2.4.0",
+    "print-js": "^1.6.0",
+    "screenfull": "4.2.0",
+    "sortable.js": "^0.3.0",
+    "umy-ui": "^1.1.6",
+    "v-charts": "^1.19.0",
+    "vue": "^2.6.11",
+    "vue-count-to": "1.0.13",
+    "vue-grid-layout": "^2.3.4",
+    "vue-i18n": "^8.17.5",
+    "vue-router": "^3.1.6",
+    "vuedraggable": "^2.21.0",
+    "vuex": "^3.1.1",
+    "xlsx": "^0.16.9"
+  },
+  "devDependencies": {
+    "@babel/core": "7.0.0",
+    "@babel/register": "7.0.0",
+    "@vue/cli-plugin-babel": "^4.2.3",
+    "@vue/cli-plugin-eslint": "^4.2.3",
+    "@vue/cli-plugin-unit-jest": "^3.8.0",
+    "@vue/cli-service": "^4.2.3",
+    "@vue/test-utils": "1.0.0-beta.29",
+    "autoprefixer": "^9.5.1",
+    "babel-core": "7.0.0-bridge.0",
+    "babel-eslint": "^10.0.1",
+    "babel-jest": "23.6.0",
+    "babel-plugin-transform-remove-console": "^6.9.4",
+    "chalk": "2.4.2",
+    "compression-webpack-plugin": "^7.1.2",
+    "connect": "3.6.6",
+    "eslint": "^6.8.0",
+    "eslint-plugin-vue": "^6.2.1",
+    "@babel/eslint-parser": "7.15.8",
+    "html-webpack-plugin": "3.2.0",
+    "mockjs": "1.0.1-beta3",
+    "node-sass": "^4.13.1",
+    "runjs": "^4.3.2",
+    "sass-loader": "^8.0.2",
+    "script-ext-html-webpack-plugin": "2.1.3",
+    "script-loader": "^0.7.2",
+    "serve-static": "^1.13.2",
+    "svg-sprite-loader": "^4.1.6",
+    "svgo": "1.2.2",
+    "terser-webpack-plugin": "^5.1.1",
+    "vue-template-compiler": "^2.6.11",
+    "webpack-bundle-analyzer": "^4.4.1"
+  },
+  "engines": {
+    "node": ">=8.9",
+    "npm": ">= 3.0.0"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions"
+  ]
+}

+ 8 - 0
postcss.config.js

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

BIN
public/favicon.ico


+ 24 - 0
public/index.html

@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
+    <!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" /> -->
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <title><%= webpackConfig.name %></title>
+  </head>
+  <body>
+    <noscript>
+      <strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+    </noscript>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+  </body>
+  <script src="//api.tianditu.gov.cn/api?v=4.0&tk=dbb376d009d74e90490af79879f33ef5" type="text/javascript"></script>
+  <script src="//lbs.tianditu.gov.cn/js/lib/jquery/jquery-1.7.2.min.js"></script>
+  <script src="//cdn.bootcss.com/d3/3.5.17/d3.js " charset="utf-8"></script>
+  <script src="//lbs.tianditu.gov.cn/api/js4.0/opensource/openlibrary/D3SvgOverlay.js"></script>
+  <script src="//lbs.tianditu.gov.cn/api/js4.0/opensource/openlibrary/CarTrack.js"></script>
+  <!-- <script language="javascript" src="//api.tianditu.gov.cn/js/maps.js"></script> -->
+</html>

+ 11 - 0
sh.exe.stackdump

@@ -0,0 +1,11 @@
+Stack trace:
+Frame        Function    Args
+000FFFFCD30  0018006286E (0018027CDD0, 0018026DE51, 000FFFFCD30, 000FFFFBA40)
+000FFFFCD30  0018004846A (00100002000, 0018034DD08, 00180350C00, 00000000001)
+000FFFFCD30  001800484A2 (00000000001, 00180350F10, 000FFFFCD30, 00100000008)
+000FFFFCD30  0018005B9D9 (001800D8DFE, 00180154E00, 00000000000, 00100000000)
+000FFFFCD30  0018005BA7D (001802288C0, 000FFFFCDF0, FFFFFFFFFFFFFFD8, 00000000000)
+000FFFFCD30  00180048C0C (00000000000, 00000000000, 00000000000, 00000000000)
+000FFFFFFF0  00180047716 (00000000000, 00000000000, 00000000000, 00000000000)
+000FFFFFFF0  001800477C4 (00000000000, 00000000000, 00000000000, 00000000000)
+End of stack trace

+ 139 - 0
src/App.vue

@@ -0,0 +1,139 @@
+<template>
+  <div id="app">
+    <router-view v-if="isRouterAlive" />
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'App',
+  provide() {
+    return {
+      reload: this.reload
+    }
+  },
+  data() {
+    return {
+      isRouterAlive: true
+    }
+  },
+  methods: {
+    reload() {
+      this.isRouterAlive = false
+      this.$nextTick(() => {
+        this.isRouterAlive = true
+      })
+    }
+  }
+}
+</script>
+<style lang="scss">
+// 弹窗最小高度
+.dialogMinHeight{
+  min-height: 450px;
+}
+.filter-container .filter-item{
+  margin-right: 3px;
+}
+.fixed-width .el-button--mini{
+  margin-right: 3px;
+}
+.el-date-editor.el-input{
+  margin-right: 3px;
+}
+
+.el-autocomplete-suggestion li{
+  padding:0 3px!important;
+}
+.filter-item .el-input__inner{
+  width: 100%;
+}
+// body .el-table th.gutter {
+//     display: table-cell !important
+// }
+
+input::-webkit-outer-spin-button,
+input::-webkit-inner-spin-button {
+  -webkit-appearance: none;
+}
+input[type="number"]{
+  -moz-appearance: textfield;
+}
+.search .filter-item{
+  margin-right: 5px;
+}
+// 开始日期结束日期
+.inputDatetime .el-range-separator{ padding: 0; margin: 0 10px; }
+
+.recipeTemplate{
+  position: absolute;
+  width: 120px;
+  height: 120px;
+  right: -50px;
+  top: -0px;
+  margin: 0;
+  background: url(assets/images/sanjiao.png) no-repeat;
+  right: -50px;
+  top: 0;
+  margin: 0;
+  p{
+    position: absolute;
+    z-index: 1;
+    color: #fff;
+    right: 40px;
+    top: 15px;
+    width: 70px;
+    -webkit-transform: rotate(45deg);
+    -moz-transform: rotate(45deg);
+    filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);/*ie*/
+    font-size: 12px;
+  }
+}
+.recipeTemplateF{
+  position: absolute;
+  width: 120px;
+  height: 120px;
+  z-index: 3;
+  right: -50px;
+  top: -0px;
+  margin: 0;
+  background: url(assets/images/sanjiao.png) no-repeat;
+  right: -50px;
+  top: 0;
+  margin: 0;
+  p{
+    position: absolute;
+    z-index: 1;
+    color: #fff;
+    right: 40px;
+    top: 15px;
+    width: 70px;
+    -webkit-transform: rotate(45deg);
+    -moz-transform: rotate(45deg);
+    filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);/*ie*/
+    font-size: 12px;
+  }
+}
+.contentOperation{
+  position: absolute;
+  width: 120px;
+  height: 120px;
+  right: -49px;
+  top: 0px;
+  margin: 0;
+  background: url(assets/images/sanjiao.png) no-repeat;
+  p{
+    position: absolute;
+    z-index: 1;
+    color: #fff;
+    right: 35px;
+    top: 17px;
+    width: 70px;
+    -webkit-transform: rotate(45deg);
+    -moz-transform: rotate(45deg);
+    filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);/*ie*/
+    font-size: 12px;
+  }
+}
+
+</style>

+ 41 - 0
src/api/article.js

@@ -0,0 +1,41 @@
+import request from '@/utils/request'
+
+export function fetchList(query) {
+  return request({
+    url: '/article/list',
+    method: 'post',
+    params: query
+  })
+}
+
+export function fetchArticle(id) {
+  return request({
+    url: '/article/detail',
+    method: 'get',
+    params: { id }
+  })
+}
+
+export function fetchPv(pv) {
+  return request({
+    url: '/article/pv',
+    method: 'get',
+    params: { pv }
+  })
+}
+
+export function createArticle(data) {
+  return request({
+    url: '/article/create',
+    method: 'post',
+    data
+  })
+}
+
+export function updateArticle(data) {
+  return request({
+    url: '/article/update',
+    method: 'post',
+    data
+  })
+}

+ 37 - 0
src/api/chart.js

@@ -0,0 +1,37 @@
+import fetch from '@/utils/fetch'
+
+export function createChart(data) {
+  return fetch({
+    url: '/chart/create',
+    method: 'POST',
+    data
+  })
+}
+
+export function updateChart(data) {
+  return fetch({
+    url: '/chart/update',
+    method: 'POST',
+    data
+  })
+}
+
+export function getChartById(id) {
+  return fetch({
+    url: `/chart/${id}`
+  })
+}
+
+export function deleteChart(data) {
+  return fetch({
+    url: `/chart/delete`,
+    method: 'POST',
+    data
+  })
+}
+
+export function chartList() {
+  return fetch({
+    url: `/chart/list`
+  })
+}

+ 466 - 0
src/api/common.js

@@ -0,0 +1,466 @@
+import request from '@/utils/request'
+import parseTime from '@/utils/index.js'
+
+export function checkDates(data) {
+  return request({
+    url: '/authdata/checkDates',
+    method: 'post',
+    data
+  })
+}
+
+
+export function GetDataByName(data) {
+  return request({
+    url: '/authdata/GetDataByName',
+    method: 'post',
+    data
+  })
+}
+
+export function processAnalysist(data) {
+  return request({
+    url: '/authdata/processAnalysist',
+    method: 'post',
+    data
+  })
+}
+
+export function ExeSqlJiade(data) {
+  return request({
+    url: '/authdata/exesql',
+    method: 'post',
+    data
+  })
+}
+export function dashboardListJiade(data) {
+  return request({
+    url: '/authdata/Dashboards',
+    method: 'post',
+    data
+  })
+}
+export function updateDashboardJiade(data) {
+  return request({
+    url: '/authdata/Updatedashboard',
+    method: 'post',
+    data
+  })
+}
+
+export function GetReportform(data) {
+  return request({
+    url: '/authdata/GetReportform',
+    method: 'post',
+    timeout: 600000,
+    data
+  })
+}
+export function requestbyname(data, requestname) {
+  return request({
+    url: '/authdata/' + requestname,
+    method: 'post',
+    data
+  })
+}
+
+export function GetDataByNameXlsx(data) {
+  return request({
+    url: '/authdata/GetDataByName',
+    method: 'post',
+    data,
+    responseType: 'blob'
+  })
+}
+
+export function GetDataByNames(data) {
+  return request({
+    url: '/authdata/GetDataByNames',
+    method: 'post',
+    data
+  })
+}
+
+export function PostDataByName(data) {
+  return request({
+    url: '/authdata/PostDataByName',
+    method: 'post',
+    data
+  })
+}
+export function GetUpkeepPlan(data) {
+  return request({
+    url: '/authdata/GetUpkeepPlan',
+    method: 'post',
+    data
+  })
+}
+export function GetAccount(data) {
+  return request({
+    url: '/authdata/GetAccount',
+    method: 'post',
+    timeout: 600000,
+    data
+  })
+}
+
+
+export function postJson(url,data) {
+  return request({
+    url: process.env.VUE_APP_BASE_API + url,
+    method: 'post',
+    timeout: 600000,
+    data
+  })
+}
+
+export function postJson2(url,data) {
+  return request({
+    url: url,
+    method: 'post',
+    timeout: 600000,
+    data
+  })
+}
+export function postJson3(url,data) {
+  return request({
+    url: url,
+    method: 'post',
+    timeout: 600000,
+    data,
+  })
+}
+
+export function getJson(url,data) {
+  return request({
+    url: process.env.VUE_APP_BASE_API + url + data,
+    method: 'get'
+  })
+}
+export function delJson(url,data) {
+  return request({
+    url: process.env.VUE_APP_BASE_API + url + data,
+    method: 'DELETE'
+  })
+}
+export function exportFile(url,data) {
+  return request({
+    url: process.env.VUE_APP_BASE_API + url,
+    method: 'post',
+    responseType: 'blob',
+    // contentType : 'application/json',
+    data
+  })
+}
+export function importFile(url,data,configHeaders) {
+  return request({
+    url: process.env.VUE_APP_BASE_API + url,
+    method: 'post',
+    configHeaders,
+    data
+  })
+}
+
+export function getData(url,data) {
+  return request({
+    url: url,
+    method: 'post',
+    timeout: 600000,
+    data
+  })
+}
+
+export function PostDataByNames(data) {
+  return request({
+    url: '/authdata/PostDataByNames',
+    method: 'post',
+    data
+  })
+}
+
+export function ExecDataByConfig(data) {
+  return request({
+    url: '/authdata/ExecDataByConfig',
+    method: 'post',
+    data
+  })
+}
+
+export function getDorm(data) {
+  return request({
+    url: '/authdata/getDorm',
+    method: 'post',
+    timeout: 6000000,
+    data
+  })
+}
+
+export function removeimage(data) {
+  return request({
+    url: '/authdata/removeimage',
+    method: 'post',
+    data
+  })
+}
+
+export function getRecuData(data) {
+  return request({
+    url: '/authdata/GetRecuDataByName',
+    method: 'post',
+    data
+  })
+}
+export function Autogeneration(data) {
+  return request({
+    url: '/authdata/autogeneration',
+    method: 'post',
+    data
+  })
+}
+export function failproccess(data, notify) {
+  if (data.data.includes('Duplicate')) {
+    notify({
+      title: '失败',
+      message: '不可以录入重复数据',
+      type: 'error',
+      duration: 2000
+    })
+  } else {
+    notify({
+      title: '失败',
+      message: '数据存在错误,请校验好重新录入,不可以录入数据',
+      type: 'error',
+      duration: 2000
+    })
+  }
+}
+
+export function UpdateDataRelation(data) {
+  return request({
+    url: '/authdata/UpdateDataRelation',
+    method: 'post',
+    data
+  })
+}
+
+export function transData(a, idStr, pidStr, chindrenStr) {
+  var r = []; var hash = {}; var id = idStr; var pid = pidStr; var children = chindrenStr; var i = 0; var j = 0; var len = a.length
+  for (; i < len; i++) {
+    hash[a[i][id]] = a[i]
+  }
+  for (; j < len; j++) {
+    var aVal = a[j]; var hashVP = hash[aVal[pid]]
+    if (hashVP) {
+      !hashVP[children] && (hashVP[children] = [])
+      hashVP[children].push(aVal)
+    } else {
+      r.push(aVal)
+    }
+  }
+  return r
+}
+
+export function checkButtons(PermissionButtons) {
+  // console.log(PermissionButtons)
+  var buttonList = JSON.parse(sessionStorage.buttonList)
+  for (let i = 0; i < buttonList.length; i++) {
+    if (buttonList[i].path === PermissionButtons) {
+      return true
+    }
+  }
+  return false
+}
+
+export function formatJson(filterVal, jsonData) {
+  return jsonData.map(v =>
+    filterVal.map(j => {
+      if (j === 'timestamp') {
+        return parseTime(v[j])
+      } else {
+        return v[j]
+      }
+    })
+  )
+}
+
+export function DownloadExcel(data, filename) {
+  const content = data
+  const blob = new Blob([content])
+  const fileName = filename + '.xlsx'
+  if ('download' in document.createElement('a')) { // 非IE下载
+    const elink = document.createElement('a')
+    elink.download = fileName
+    elink.style.display = 'none'
+    elink.href = URL.createObjectURL(blob)
+    document.body.appendChild(elink)
+    elink.click()
+    URL.revokeObjectURL(elink.href) // 释放URL 对象
+    document.body.removeChild(elink)
+  } else { // IE10+下载
+    navigator.msSaveBlob(blob, fileName)
+  }
+}
+// 取小数
+// export function formatNum(f, digit) {
+//   var m = Math.pow(10, digit);
+//   return parseInt(f * m, 10) / m;
+// }
+export function formatNum(value, n) {
+  var f = Math.round(value*Math.pow(10,n))/Math.pow(10,n);
+  var s = f.toString();
+  var rs = s.indexOf('.');
+  if(rs < 0) {
+    s += '.';
+  }
+  for(var i = s.length - s.indexOf('.'); i <= n; i++){
+    s += "0";
+  }
+  return s;
+}
+
+export function compareSort(property){
+  return function(a,b){
+    var value1 = a[property];
+    var value2 = b[property];
+    return value1 - value2;
+  }
+}
+
+
+//将日期转换成一年中的第几周
+export function getYearWeek(date) {
+  //按照国际标准
+  let time,
+    week,
+    checkDate = new Date(date);
+  checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
+  time = checkDate.getTime();
+  checkDate.setMonth(0);
+  checkDate.setDate(1);
+  week = Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
+  return week;
+}
+
+//返回格式 2019年第23周,特别注意跨年一周的问题
+export function getYearAndWeek(date, anotherDate) {
+  let week = getYearWeek(date);
+  let year = date.substring(0, 4);
+  let anotherYear = anotherDate.substring(0, 4);
+  //处理跨年特殊日期
+  if (anotherDate > date) {
+    let betweenDay = getBetweenDay(new Date(date), new Date(anotherDate));
+    if (betweenDay == 7 && anotherYear != year) {
+      if (week == 1) {
+        year = parseInt(year) + 1;
+      }
+    }
+  } else {
+    let betweenDay = getBetweenDay(new Date(anotherDate), new Date(date));
+    if (betweenDay == 7 && anotherYear != year) {
+      if (week != 1) {
+        year = parseInt(year) - 1;
+      }
+    }
+  }
+  return `${year}年第${week}周`;
+}
+export function getBetweenDay(beginDate, endDate) {
+  let dateSpan = endDate - beginDate;
+  dateSpan = Math.abs(dateSpan);
+  let days = Math.floor(dateSpan / (24 * 3600 * 1000));
+  return days + 1;
+}
+//获取当前count个周的起止日期,如:count=0 ,就是当前周,-1就是上周,以此类推
+export function getWeekStartAndEnd(count, currentDate) {
+  //起止日期数组
+  let resultArr = new Array();
+  let millisecond = 1000 * 60 * 60 * 24;
+  currentDate = new Date(currentDate.getTime() + millisecond * 7 * count);
+  let week = currentDate.getDay();
+
+  //减去的天数
+  let minusDay = week != 0 ? week - 1 : 6;
+  //获得当前周的第一天
+  let currentWeekFirstDay = new Date(
+    currentDate.getTime() - millisecond * minusDay
+  );
+  //获得当前周的最后一天
+  let currentWeekLastDay = new Date(
+    currentWeekFirstDay.getTime() + millisecond * 6
+  );
+
+  resultArr.push(currentWeekFirstDay.format());
+  resultArr.push(currentWeekLastDay.format());
+  return resultArr;
+}
+Date.prototype.format = function() {
+  let s = "";
+  let mouth =
+    this.getMonth() + 1 >= 10
+      ? this.getMonth() + 1
+      : "0" + (this.getMonth() + 1);
+  let day = this.getDate() >= 10 ? this.getDate() : "0" + this.getDate();
+  s += this.getFullYear() + "-"; // 获取年份。
+  s += mouth + "-"; // 获取月份。
+  s += day; // 获取日。
+  return s; // 返回日期。
+};
+
+/**
+ * @param date 传入的日期
+ * @param num 加减的天数,加为正,减为负
+ * @returns 格式化后的日期
+ */
+export function addDays(date, num) {
+  date.setDate(date.getDate() + num);
+  return date.format();
+}
+
+export function yearDay(long) {
+  var time = new Date(long * 1000)
+  var year = time.getFullYear()
+  var month = (time.getMonth() + 1) < 10 ? '0' + (time.getMonth() + 1) : (time.getMonth() + 1)
+  var date = time.getDate() < 10 ? '0' + time.getDate() : time.getDate()
+  var yearday = { year, month, date }
+  return yearday
+}
+
+// 计算一年中的每一周都是从几号到几号
+// 第一周为1月1日到 本年的 第一个周日
+// 第二周为 本年的 第一个周一 往后推到周日
+// 以此类推 再往后推52周。。。
+// 如果最后一周在12月31日之前,则本年有垮了54周,反之53周
+// 12月31 日不论是周几,都算为本周的最后一天
+// 参数年份 ,函数返回一个数组,数组里的对象包含 这一周的开始日期和结束日期
+export function whichWeek(year) {
+      var d = new Date(year, 0, 1)
+      while (d.getDay() != 1) {
+        d.setDate(d.getDate() + 1)
+      }
+      const arr = []
+      const longnum = d.setDate(d.getDate())
+      if (longnum > +new Date(year, 0, 1)) {
+        const obj = yearDay(+new Date(year, 0, 1) / 1000)
+        obj.last = yearDay(longnum / 1000 - 86400)
+        arr.push(obj)
+      }
+      const oneitem = yearDay(longnum / 1000)
+      oneitem.last = yearDay(longnum / 1000 + 86400 * 6)
+      arr.push(oneitem)
+      var lastStr
+      for (var i = 0; i < 51; i++) {
+        const long = d.setDate(d.getDate() + 7)
+        const obj = yearDay(long / 1000)
+        obj.last = yearDay(long / 1000 + 86400 * 6)
+        lastStr = long + 86400000 * 6
+        arr.push(obj)
+      }
+      if (lastStr < +new Date(year + 1, 0, 1)) {
+        const obj = yearDay(lastStr / 1000 + 86400)
+        obj.last = yearDay(+new Date(year + 1, 0, 1) / 1000 - 86400)
+        arr.push(obj)
+      } else {
+        arr[arr.length - 1].last = yearDay(+new Date(year + 1, 0, 1) / 1000 - 86400)
+      }
+      return arr
+    }

+ 73 - 0
src/api/dashboard.js

@@ -0,0 +1,73 @@
+import fetch from '@/utils/fetch'
+
+export function addDashboard(data) {
+  return fetch({
+    url: '/dashboard/create',
+    method: 'POST',
+    data
+  })
+}
+
+export function updateDashboard(data) {
+  return fetch({
+    url: '/dashboard/update',
+    method: 'POST',
+    data
+  })
+}
+
+export function getdDashboardById(id) {
+  return fetch({
+    url: `/dashboard/${id}`
+  })
+}
+
+export function deleteDashboard(data) {
+  return fetch({
+    url: `/dashboard/delete`,
+    method: 'post',
+    data
+  })
+}
+
+export function dashboardList() {
+  return fetch({
+    url: `/dashboard/list`
+  })
+}
+
+export function addChartToDB(data) {
+  return fetch({
+    url: '/chartboard/map',
+    method: 'POST',
+    data
+  })
+}
+
+export function chartByDashboard(id) {
+  return fetch({
+    url: `/chartboardmap/chartbydashboard?dashboard_id=${id}`
+  })
+}
+
+export function dbByChart(id) {
+  return fetch({
+    url: `/chartboardmap/boardbychart?chart_id=${id}`
+  })
+}
+
+export function unMapChartDb(data) {
+  return fetch({
+    url: '/chartboard/unmap',
+    method: 'POST',
+    data
+  })
+}
+
+export function dbOrder(data) {
+  return fetch({
+    url: '/dashboard/order',
+    method: 'POST',
+    data
+  })
+}

+ 49 - 0
src/api/dept.js

@@ -0,0 +1,49 @@
+import request from '@/utils/request'
+
+export function fetchList(data) {
+  return request({
+    url: '/authdata/GetRecuDataByName',
+    method: 'post',
+    data
+  })
+}
+
+export function fetchArticle(id) {
+  return request({
+    url: '/article/detail',
+    method: 'get',
+    params: { id }
+  })
+}
+
+export function fetchPv(pv) {
+  return request({
+    url: '/article/pv',
+    method: 'get',
+    params: { pv }
+  })
+}
+
+export function createDept(data) {
+  return request({
+    url: '/authdata/PostDataByName',
+    method: 'post',
+    data
+  })
+}
+
+export function updateDept(data) {
+  return request({
+    url: '/article/update',
+    method: 'post',
+    data
+  })
+}
+
+export function getRecuDept(data) {
+  return request({
+    url: '/authdata/getrecudatabyname',
+    method: 'post',
+    data
+  })
+}

+ 22 - 0
src/api/exeSql.js

@@ -0,0 +1,22 @@
+import fetch from '@/utils/fetch'
+import axios from 'axios'
+
+export default function() {
+  const source = axios.CancelToken.source()
+  return {
+    cancel() {
+      source.cancel('cancel')
+    },
+    fetch(data) {
+      return fetch({
+        url: `/authdata/exesql`,
+        cancelToken: source.token,
+        headers: {
+          'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
+        },
+        method: 'POST',
+        data
+      })
+    }
+  }
+}

+ 11 - 0
src/api/menu.js

@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+/**
+  *根据角色获得可见菜单
+  */
+export function getMenuByRole(data) {
+  return request({
+    url: '/authdata/rolemenus',
+    method: 'post',
+    data
+  })
+}

+ 17 - 0
src/api/remote-search.js

@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+export function searchUser(name) {
+  return request({
+    url: '/search/user',
+    method: 'get',
+    params: { name }
+  })
+}
+
+export function transactionList(query) {
+  return request({
+    url: '/transaction/list',
+    method: 'get',
+    params: query
+  })
+}

+ 54 - 0
src/api/source.js

@@ -0,0 +1,54 @@
+import fetch from '@/utils/fetch'
+
+export function addSource(data) {
+  return fetch({
+    url: 'source/create',
+    method: 'POST',
+    data
+  })
+}
+
+export function updateSource(data) {
+  return fetch({
+    url: 'source/update',
+    method: 'POST',
+    data
+  })
+}
+
+export function deleteSource(data) {
+  return fetch({
+    url: 'source/delete',
+    method: 'POST',
+    data
+  })
+}
+
+export function sourceList() {
+  return fetch({
+    url: 'source/list',
+    method: 'get'
+  })
+}
+
+export function tablesByBase(sourceId) {
+  return fetch({
+    url: `source/tables/${sourceId}`,
+    method: 'get'
+  })
+}
+
+export function saveTableConfig(data) {
+  return fetch({
+    url: 'source/tables/save',
+    method: 'POST',
+    data
+  })
+}
+
+export function linkedTablesByBase(sourceId) {
+  return fetch({
+    url: `source/tables/${sourceId}/linked`,
+    method: 'get'
+  })
+}

+ 9 - 0
src/api/table.js

@@ -0,0 +1,9 @@
+import request from '@/utils/request'
+
+export function getList(params) {
+  return request({
+    url: '/table/list',
+    method: 'get',
+    params
+  })
+}

+ 24 - 0
src/api/user.js

@@ -0,0 +1,24 @@
+import request from '@/utils/request'
+
+export function login(data) {
+  return request({
+    url: '/auth',
+    method: 'post',
+    data
+  })
+}
+
+export function getInfo() { // token
+  return request({
+    url: '/api/v1/system/user_info',
+    method: 'post'
+    // params: { token }
+  })
+}
+
+export function logout() {
+  return request({
+    url: '/authdata/logout',
+    method: 'post'
+  })
+}

BIN
src/assets/404_images/404.png


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


BIN
src/assets/cow.jpg


BIN
src/assets/custom-theme/fonts/element-icons.ttf


ファイルの差分が大きいため隠しています
+ 0 - 0
src/assets/custom-theme/index.css


ファイルの差分が大きいため隠しています
+ 3 - 0
src/assets/iconfont/iconfont.css


BIN
src/assets/iconfont/iconfont.eot


ファイルの差分が大きいため隠しています
+ 0 - 0
src/assets/iconfont/iconfont.js


ファイルの差分が大きいため隠しています
+ 28 - 0
src/assets/iconfont/iconfont.svg


BIN
src/assets/iconfont/iconfont.ttf


BIN
src/assets/iconfont/iconfont.woff


BIN
src/assets/iconfont/iconfont.woff2


BIN
src/assets/images/index/l1.png


BIN
src/assets/images/index/l2.png


BIN
src/assets/images/index/l3.png


BIN
src/assets/images/index/l4.png


BIN
src/assets/images/index/row-bg1.png


BIN
src/assets/images/index/row-bg2.png


BIN
src/assets/images/index/row-bg3.png


BIN
src/assets/images/index/row-l1.png


BIN
src/assets/images/index/row-l2.png


BIN
src/assets/images/index/row-r1.png


BIN
src/assets/images/index/row-r10.png


BIN
src/assets/images/index/row-r2.png


BIN
src/assets/images/index/row-r3.png


BIN
src/assets/images/index/row-r4.png


BIN
src/assets/images/index/row-r5.png


BIN
src/assets/images/index/row-r6.png


BIN
src/assets/images/index/row-r7.png


BIN
src/assets/images/index/row-r8.png


BIN
src/assets/images/index/row-r9.png


BIN
src/assets/images/index/t1.png


BIN
src/assets/images/index/t2.png


BIN
src/assets/images/index/t3.png


BIN
src/assets/images/index/t4.png


BIN
src/assets/images/index/topBg.png


BIN
src/assets/images/logo.png


BIN
src/assets/images/logo1.png


BIN
src/assets/images/logo_u3.png


BIN
src/assets/images/materiallssuancePlan/bg1.png


BIN
src/assets/images/nlogin-bg.png


BIN
src/assets/images/nlogin-bg1.jpg


BIN
src/assets/images/nlogin-bg2.png


BIN
src/assets/images/nlogin-bg3.png


BIN
src/assets/images/nlogo1.png


BIN
src/assets/images/nlogo2.png


BIN
src/assets/images/sanjiao.png


+ 117 - 0
src/componentChart/BarChart.vue

@@ -0,0 +1,117 @@
+<template>
+  <div ref="chart"  style="width:100%;height:385px;"  />
+</template>
+<script>
+import echarts from 'echarts'
+import { GetDataByName } from '@/api/common'
+import draggable from 'vuedraggable'
+import Cookies from 'js-cookie'
+import { parseTime } from '@/utils/index.js'
+import Pagination from '@/components/Pagination'
+require('echarts/theme/macarons')
+
+export default {
+  name: 'BarChart',
+  props: {
+    
+
+    chartData: {
+      type: Object,
+      required: true
+    },
+    //   chartOpt: {
+    //   type: Object,
+    //   required: false
+    // },
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  watch: {
+    chartData: {
+      deep: true,
+      handler: function (chartData) {
+        this.renderChart(chartData)
+      }
+    },
+    // schema: {
+    //   deep: true,
+    //   handler: function () {
+    //     this.renderChart(this.data)
+    //   }
+    // }
+  },
+  mounted() {
+    this.renderChart(this.chartData)
+    this.$on('resized', this.handleResize)
+    window.addEventListener('resize', this.handleResize)
+  },
+
+
+  // created() {
+  //   this.renderChart(this.chartData)
+  // },
+  beforeDestroy() {
+    if (this.chart) {
+      this.chart.dispose()
+    }
+    window.removeEventListener('resize', this.handleResize)
+  },
+  methods: {
+    handleResize() {
+      if (this.chart) {
+        this.chart.resize()
+      }
+    },
+    renderChart(chartData) {
+      const option =  {
+        title: { text: '' },
+        tooltip: { trigger: 'axis' },
+        legend: {   data:chartData.legendArr, right: 10, show: true, type: 'scroll' },
+        grid: { top: '15%', left: '8%', right: '8%', containLabel: true },
+        xAxis: [{ type: 'category',data:chartData.xAxisArr }],
+        yAxis: [
+          {type: 'value'},  
+        ],
+         series: function (e) {
+            var serie = [];
+            for (var i = 0; i < chartData.xAxisArr.length; i++) {
+              console.log(i)
+               
+                var item = {
+                  name: chartData.legendArr[i],
+                  data: chartData.dataArr[i],
+                  type: 'bar',
+                  emphasis: { label: { show: true, position: 'inside' } },
+                }
+             
+
+              serie.push(item);
+            }
+
+
+            console.log(serie)
+
+            return serie;
+          }()
+      
+      }
+      setTimeout(() => {
+        if (!this.chart) {
+          this.chart = echarts.init(this.$refs.chart, 'macarons')
+        }
+        this.chart.clear()
+        this.chart.setOption(option)
+        // if (this.chartOpt) {
+        //   this.chart.setOption(this.chartOpt)
+        // }
+ 
+        this.chart.setOption(this.chartOpt)
+       
+      }, 0)
+    }
+  }
+}
+</script>

+ 185 - 0
src/componentChart/ChartTable.vue

@@ -0,0 +1,185 @@
+<template>
+  <div class="app-table">
+   
+        <div class="table">
+          <el-table
+            :key="tableObj.tableKey"
+            v-loading="tableObj.listLoading"
+            element-loading-text="给我一点时间"
+            :data="tableObj.list"
+            border
+            fit
+            highlight-current-row
+            style="width: 100%;"
+            :row-style="rowStyle"
+            :cell-style="cellStyle"
+            class="elTable table-fixed" 
+          >
+         
+            <el-table-column label="序号" align="center" type="index" width="50px">
+              <template slot-scope="scope">
+                <span v-if="tableObj.pageNum">{{ scope.$index + (tableObj.pageNum-1) * tableObj.pageSize + 1 }}</span>
+                <span v-else>1</span>
+              </template>
+            </el-table-column>
+
+
+      
+
+
+
+            <el-table-column label="分日日期/维度" min-width="130px" align="center">
+              <template slot-scope="scope">
+                <span>{{ scope.row.date }}</span>
+              </template>
+            </el-table-column>
+
+
+            <!-- <el-table-column label="混料数据" min-width="130px" align="center">
+              <el-table-column label="理论重量" min-width="130px" align="center">
+                <template slot-scope="scope">
+                  <span>{{ scope.row.drivercode }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="实际重量" min-width="130px" align="center">
+                <template slot-scope="scope">
+                  <span>{{ scope.row.drivercode }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="误差值" min-width="130px" align="center">
+                <template slot-scope="scope">
+                  <span>{{ scope.row.drivercode }}</span>
+                </template>
+              </el-table-column>
+            </el-table-column> -->
+
+            <el-table-column :label="item.label" min-width="130px" align="center" v-for=" (item,index) in tableHead">
+
+              <el-table-column :label="items.label" :property="item.value" min-width="130px" align="center" v-for=" (items,indexs) in item.children">
+                <template slot-scope="scope">
+                  <span>{{ scope.row[items.value] }}</span>
+                </template>
+              </el-table-column>
+               
+            </el-table-column>
+
+            
+           
+           
+           
+          </el-table>
+          <pagination v-show="tableObj.total>0" :total="tableObj.total" :page.sync="tableObj.getDataParameters.offset" :limit.sync="tableObj.getDataParameters.pagecount" @pagination="getList" />
+        </div>
+   
+   
+  </div>
+</template>
+
+<script>
+import { GetDataByName } from '@/api/common'
+import draggable from 'vuedraggable'
+import Cookies from 'js-cookie'
+import { parseTime } from '@/utils/index.js'
+import Pagination from '@/components/Pagination'
+
+
+
+export default {
+  name: 'ChartTable',
+  components: { Pagination },
+
+  props: {
+   
+  },
+  data() {
+    return {
+
+      tableHead:[
+        { 
+          value: 'txt1',label: '混料数据',
+          children: [
+            { value: 'txt11', label: '理论重量-合计'}, 
+            { value: 'txt12', label: '理论重量-平均'}, 
+            { value: 'txt13', label: '理论重量-最大值'}, 
+          ]
+        },
+        { 
+          value: 'txt2',label: '撒料数据',
+          children: [
+            { value: 'txt21', label: '理论重量-合计'}, 
+            { value: 'txt22', label: '理论重量-平均'}, 
+            { value: 'txt23', label: '理论重量-最大值'}, 
+          ]
+        }
+      ],
+      tableObj: {
+         getDataParameters: {
+          name: 'getDriverList',
+          page: 1,
+          offset: 1,
+          pagecount: parseInt(Cookies.get('pageCount')),
+          returntype: 'Map',
+          parammaps: {
+            pastureid: Cookies.get('pastureid'),
+            dateType:'',
+            type: '',
+            dimension: '',
+            mixture: [],
+            spread: [],
+          }
+        },
+        tableKey: 0,
+        list: [
+           { id:1,date:1212,txt11:11,txt12:12,txt13:13,txt21:21,txt22:22,txt23:23,},
+            { id:1,date:1212,txt11:11,txt12:12,txt13:13,txt21:21,txt22:22,txt23:23,},
+             { id:1,date:1212,txt11:11,txt12:12,txt13:13,txt21:21,txt22:22,txt23:23,}
+        ],
+        total: 0,
+        listLoading: false,
+        temp: {}
+      },
+
+  
+
+      rowStyle: { maxHeight: 30 + 'px', height: 30 + 'px' },
+      cellStyle: { padding: 0 + 'px' }
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+   
+    getList() {
+
+     
+      //this.tableObj.listLoading = true
+      // GetDataByName(this.tableObj.getdataListParm).then(response => {
+      //   console.log('table数据', response.data.list)
+      //   if (response.data.list !== null) {
+      //     this.tableObj.list = response.data.list
+      //     this.tableObj.pageNum = response.data.pageNum
+      //     this.tableObj.pageSize = response.data.pageSize
+      //     this.tableObj.total = response.data.total
+      //   } else {
+      //     this.tableObj.list = []
+      //   }
+      //   setTimeout(() => {
+      //     this.tableObj.listLoading = false
+      //   }, 100)
+      // })
+
+      this.tableObj.listLoading = false
+     
+    },
+
+  
+   
+    
+  }
+}
+</script>
+
+<style  lang="scss" scoped>
+ .search{margin-bottom: 10px;}
+</style>

+ 121 - 0
src/componentChart/HorizontalBarChart.vue

@@ -0,0 +1,121 @@
+<template>
+  <div ref="chart"  style="width:100%;height:385px;"  />
+</template>
+<script>
+import echarts from 'echarts'
+import { GetDataByName } from '@/api/common'
+import draggable from 'vuedraggable'
+import Cookies from 'js-cookie'
+import { parseTime } from '@/utils/index.js'
+import Pagination from '@/components/Pagination'
+require('echarts/theme/macarons')
+
+export default {
+  name: 'HorizontalBarChart',
+  props: {
+    
+
+    chartData: {
+      type: Object,
+      required: true
+    },
+    //   chartOpt: {
+    //   type: Object,
+    //   required: false
+    // },
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  watch: {
+    chartData: {
+      deep: true,
+      handler: function (chartData) {
+        this.renderChart(chartData)
+      }
+    },
+    // schema: {
+    //   deep: true,
+    //   handler: function () {
+    //     this.renderChart(this.data)
+    //   }
+    // }
+  },
+  mounted() {
+    this.renderChart(this.chartData)
+    this.$on('resized', this.handleResize)
+    window.addEventListener('resize', this.handleResize)
+  },
+
+
+  // created() {
+  //   this.renderChart(this.chartData)
+  // },
+  beforeDestroy() {
+    if (this.chart) {
+      this.chart.dispose()
+    }
+    window.removeEventListener('resize', this.handleResize)
+  },
+  methods: {
+    handleResize() {
+      if (this.chart) {
+        this.chart.resize()
+      }
+    },
+    renderChart(chartData) {
+      const option =  {
+        title: { text: '' },
+        tooltip: { trigger: 'axis' },
+        legend: {   data:chartData.legendArr, right: 10, show: true, type: 'scroll' },
+        grid: { top: '15%', left: '8%', right: '8%', containLabel: true },
+
+         xAxis: {type: 'value', name: 'kg'},
+        yAxis: [
+          { type: 'category',data:chartData.xAxisArr }
+           
+        ],
+
+       
+         series: function (e) {
+            var serie = [];
+            for (var i = 0; i < chartData.xAxisArr.length; i++) {
+              console.log(i)
+               
+                var item = {
+                  name: chartData.legendArr[i],
+                  data: chartData.dataArr[i],
+                  type: 'bar',
+                  emphasis: { label: { show: true, position: 'inside' } },
+                }
+             
+
+              serie.push(item);
+            }
+
+
+            console.log(serie)
+
+            return serie;
+          }()
+      
+      }
+      setTimeout(() => {
+        if (!this.chart) {
+          this.chart = echarts.init(this.$refs.chart, 'macarons')
+        }
+        this.chart.clear()
+        this.chart.setOption(option)
+        // if (this.chartOpt) {
+        //   this.chart.setOption(this.chartOpt)
+        // }
+ 
+        this.chart.setOption(this.chartOpt)
+       
+      }, 0)
+    }
+  }
+}
+</script>

+ 135 - 0
src/componentChart/LineBarChart.vue

@@ -0,0 +1,135 @@
+<template>
+  <div ref="chart"  style="width:100%;height:385px;"  />
+</template>
+<script>
+import echarts from 'echarts'
+import { GetDataByName } from '@/api/common'
+import draggable from 'vuedraggable'
+import Cookies from 'js-cookie'
+import { parseTime } from '@/utils/index.js'
+import Pagination from '@/components/Pagination'
+require('echarts/theme/macarons')
+
+export default {
+  name: 'LineBarChart',
+  props: {
+    
+
+    chartData: {
+      type: Object,
+      required: true
+    },
+    //   chartOpt: {
+    //   type: Object,
+    //   required: false
+    // },
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  watch: {
+    chartData: {
+      deep: true,
+      handler: function (chartData) {
+        this.renderChart(chartData)
+      }
+    },
+    // schema: {
+    //   deep: true,
+    //   handler: function () {
+    //     this.renderChart(this.data)
+    //   }
+    // }
+  },
+  mounted() {
+    this.renderChart(this.chartData)
+    this.$on('resized', this.handleResize)
+    window.addEventListener('resize', this.handleResize)
+  },
+
+
+  // created() {
+  //   this.renderChart(this.chartData)
+  // },
+  beforeDestroy() {
+    if (this.chart) {
+      this.chart.dispose()
+    }
+    window.removeEventListener('resize', this.handleResize)
+  },
+  methods: {
+    handleResize() {
+      if (this.chart) {
+        this.chart.resize()
+      }
+    },
+    renderChart(chartData) {
+      var legendArrRe  = chartData.legendArr1.concat(chartData.legendArr2)
+      const option =  {
+
+        
+        title: { text: 'Stacked Line' },
+        tooltip: { trigger: 'axis' },
+        legend: {   data:legendArrRe, right: 10, show: true, type: 'scroll' },
+        grid: { top: '15%', left: '8%', right: '8%', containLabel: true },
+        xAxis: [{ type: 'category',data:chartData.xAxisArr }],
+        yAxis: [
+          {type: 'value', name: 'kg'},
+           
+        ],
+         series: function (e) {
+            var serie = [];
+            for (var i = 0; i < chartData.xAxisArr.length; i++) {
+              console.log(i)
+               
+                var item = {
+                  name: chartData.legendArr1[i],
+                  data: chartData.dataArr1[i],
+                  type: 'line',
+                  emphasis: { label: { show: true, position: 'inside' } },
+                }
+             
+
+              serie.push(item);
+            }
+
+            for (var i = 0; i < chartData.xAxisArr.length; i++) {
+              console.log(i)
+               
+                var item = {
+                  name: chartData.legendArr2[i],
+                  data: chartData.dataArr2[i],
+                  type: 'bar',
+                  emphasis: { label: { show: true, position: 'inside' } },
+                }
+             
+
+              serie.push(item);
+            }
+
+
+            console.log(serie)
+
+            return serie;
+          }()
+      
+      }
+      setTimeout(() => {
+        if (!this.chart) {
+          this.chart = echarts.init(this.$refs.chart, 'macarons')
+        }
+        this.chart.clear()
+        this.chart.setOption(option)
+        // if (this.chartOpt) {
+        //   this.chart.setOption(this.chartOpt)
+        // }
+ 
+        this.chart.setOption(this.chartOpt)
+       
+      }, 0)
+    }
+  }
+}
+</script>

+ 118 - 0
src/componentChart/LineChart.vue

@@ -0,0 +1,118 @@
+<template>
+  <div ref="chart"  style="width:100%;height:385px;"  />
+</template>
+<script>
+import echarts from 'echarts'
+import { GetDataByName } from '@/api/common'
+import draggable from 'vuedraggable'
+import Cookies from 'js-cookie'
+import { parseTime } from '@/utils/index.js'
+import Pagination from '@/components/Pagination'
+require('echarts/theme/macarons')
+
+export default {
+  name: 'LineChart',
+  props: {
+    
+
+    chartData: {
+      type: Object,
+      required: true
+    },
+    //   chartOpt: {
+    //   type: Object,
+    //   required: false
+    // },
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  watch: {
+    chartData: {
+      deep: true,
+      handler: function (chartData) {
+        this.renderChart(chartData)
+      }
+    },
+    // schema: {
+    //   deep: true,
+    //   handler: function () {
+    //     this.renderChart(this.data)
+    //   }
+    // }
+  },
+  mounted() {
+    this.renderChart(this.chartData)
+    this.$on('resized', this.handleResize)
+    window.addEventListener('resize', this.handleResize)
+  },
+
+
+  // created() {
+  //   this.renderChart(this.chartData)
+  // },
+  beforeDestroy() {
+    if (this.chart) {
+      this.chart.dispose()
+    }
+    window.removeEventListener('resize', this.handleResize)
+  },
+  methods: {
+    handleResize() {
+      if (this.chart) {
+        this.chart.resize()
+      }
+    },
+    renderChart(chartData) {
+      const option =  {
+        title: { text: 'Stacked Line' },
+        tooltip: { trigger: 'axis' },
+        legend: {   data:chartData.legendArr, right: 10, show: true, type: 'scroll' },
+        grid: { top: '15%', left: '8%', right: '8%', containLabel: true },
+        xAxis: [{ type: 'category',data:chartData.xAxisArr }],
+        yAxis: [
+          {type: 'value', name: 'kg'},
+           
+        ],
+         series: function (e) {
+            var serie = [];
+            for (var i = 0; i < chartData.xAxisArr.length; i++) {
+              console.log(i)
+               
+                var item = {
+                  name: chartData.legendArr[i],
+                  data: chartData.dataArr[i],
+                  type: 'line',
+                  emphasis: { label: { show: true, position: 'inside' } },
+                }
+             
+
+              serie.push(item);
+            }
+
+
+            console.log(serie)
+
+            return serie;
+          }()
+      
+      }
+      setTimeout(() => {
+        if (!this.chart) {
+          this.chart = echarts.init(this.$refs.chart, 'macarons')
+        }
+        this.chart.clear()
+        this.chart.setOption(option)
+        // if (this.chartOpt) {
+        //   this.chart.setOption(this.chartOpt)
+        // }
+ 
+        this.chart.setOption(this.chartOpt)
+       
+      }, 0)
+    }
+  }
+}
+</script>

+ 138 - 0
src/componentChart/PieChart.vue

@@ -0,0 +1,138 @@
+<template>
+  <div ref="chart"  style="width:100%;height:385px;"  />
+</template>
+<script>
+import echarts from 'echarts'
+import { GetDataByName } from '@/api/common'
+import draggable from 'vuedraggable'
+import Cookies from 'js-cookie'
+import { parseTime } from '@/utils/index.js'
+import Pagination from '@/components/Pagination'
+require('echarts/theme/macarons')
+
+export default {
+  name: 'PieChart',
+  props: {
+    
+
+    chartData: {
+      type: Object,
+      required: true
+    },
+    //   chartOpt: {
+    //   type: Object,
+    //   required: false
+    // },
+  },
+  data() {
+    return {
+      chart: null
+    }
+  },
+  watch: {
+    chartData: {
+      deep: true,
+      handler: function (chartData) {
+        this.renderChart(chartData)
+      }
+    },
+    // schema: {
+    //   deep: true,
+    //   handler: function () {
+    //     this.renderChart(this.data)
+    //   }
+    // }
+  },
+  mounted() {
+    this.renderChart(this.chartData)
+    this.$on('resized', this.handleResize)
+    window.addEventListener('resize', this.handleResize)
+  },
+
+
+  // created() {
+  //   this.renderChart(this.chartData)
+  // },
+  beforeDestroy() {
+    if (this.chart) {
+      this.chart.dispose()
+    }
+    window.removeEventListener('resize', this.handleResize)
+  },
+  methods: {
+    handleResize() {
+      if (this.chart) {
+        this.chart.resize()
+      }
+    },
+    renderChart(chartData) {
+      const option =  {
+        title: { text: 'Stacked Line' },
+        tooltip: { trigger: 'axis' },
+        legend: {   data:chartData.legendArr, right: 10, show: true, type: 'scroll' },
+        grid: { top: '15%', left: '8%', right: '8%', containLabel: true },
+        xAxis: [{ type: 'category',data:chartData.xAxisArr }],
+        yAxis: [
+          {type: 'value', name: 'kg'},
+           
+        ],
+         series: function (e) {
+             
+              var serie = [
+               {
+                  name: 'Access From',
+                  type: 'pie',
+                  radius: '50%',
+                  data: [
+                    // { value: 1048, name: 'Search Engine' },
+                    // { value: 735, name: 'Direct' },
+                    // { value: 580, name: 'Email' },
+                    // { value: 484, name: 'Union Ads' },
+                    // { value: 300, name: 'Video Ads' }
+                  ],
+                  emphasis: {
+                    itemStyle: {
+                      shadowBlur: 10,
+                      shadowOffsetX: 0,
+                      shadowColor: 'rgba(0, 0, 0, 0.5)'
+                    }
+                  }
+                }
+              ];
+            for (var i = 0; i < chartData.xAxisArr.length; i++) {
+              console.log(i)
+               
+                var item = {
+                  name: chartData.legendArr[i],
+                  value: chartData.dataArr[i],
+                
+                }
+             
+
+              serie[0].data.push(item);
+            }
+
+
+            console.log("饼图:",serie)
+
+            return serie;
+          }()
+      
+      }
+      setTimeout(() => {
+        if (!this.chart) {
+          this.chart = echarts.init(this.$refs.chart, 'macarons')
+        }
+        this.chart.clear()
+        this.chart.setOption(option)
+        // if (this.chartOpt) {
+        //   this.chart.setOption(this.chartOpt)
+        // }
+ 
+        this.chart.setOption(this.chartOpt)
+       
+      }, 0)
+    }
+  }
+}
+</script>

+ 79 - 0
src/components/Breadcrumb/index.vue

@@ -0,0 +1,79 @@
+<template>
+  <el-breadcrumb class="app-breadcrumb" separator="/">
+    <transition-group name="breadcrumb">
+      <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
+        <span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
+        <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
+      </el-breadcrumb-item>
+    </transition-group>
+  </el-breadcrumb>
+</template>
+
+<script>
+import pathToRegexp from 'path-to-regexp'
+
+export default {
+  data() {
+    return {
+      levelList: null
+    }
+  },
+  watch: {
+    $route() {
+      this.getBreadcrumb()
+    }
+  },
+  created() {
+    this.getBreadcrumb()
+  },
+  methods: {
+    getBreadcrumb() {
+      // only show routes with meta.title
+      let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
+      const first = matched[0]
+
+      if (!this.isDashboard(first)) {
+        matched = [{ path: '/dashboard', meta: { title: '首页' }}].concat(matched)
+      }
+
+      this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
+      console.log(this.levelList,'this.levelList')
+    },
+    isDashboard(route) {
+      const name = route && route.name
+      if (!name) {
+        return false
+      }
+      return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
+    },
+    pathCompile(path) {
+      // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
+      const { params } = this.$route
+      var toPath = pathToRegexp.compile(path)
+      return toPath(params)
+    },
+    handleLink(item) {
+      const { redirect, path } = item
+      if (redirect) {
+        this.$router.push(redirect)
+        return
+      }
+      this.$router.push(this.pathCompile(path))
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.app-breadcrumb.el-breadcrumb {
+  display: inline-block;
+  font-size: 14px;
+  line-height: 50px;
+  margin-left: 8px;
+
+  .no-redirect {
+    color: #97a8be;
+    cursor: text;
+  }
+}
+</style>

+ 141 - 0
src/components/ChartTable.vue

@@ -0,0 +1,141 @@
+<template>
+  <div class="app-table">
+   
+    <div class="table">
+      <el-table
+        :key="table.tableKey"
+        v-loading="table.listLoading"
+        element-loading-text="给我一点时间"
+        :data="table.list"
+        border
+        fit
+        highlight-current-row
+        style="width: 100%;"
+        :row-style="rowStyle"
+        :cell-style="cellStyle"
+        class="elTable table-fixed"
+      >
+        <el-table-column :key="1" label="序号" prop="sort" align="center" width="50px" />
+        <el-table-column :key="2" label="栏舍名称" prop="barname" min-width="90px" align="center" />
+        <el-table-column :key="3" label="第一层" min-width="90px" align="center">
+          <el-table-column label="比例 (%)" prop="onerate" min-width="90px" align="center" />
+          <el-table-column label="重量 (g)" prop="oneweight" min-width="90px" align="center" />
+        </el-table-column>
+        <el-table-column :key="4" label="第二层" min-width="90px" align="center">
+          <el-table-column label="比例 (%)" prop="tworate" min-width="90px" align="center" />
+          <el-table-column label="重量 (g)" prop="twoweight" min-width="90px" align="center" />
+        </el-table-column>
+        <el-table-column :key="5" label="第三层" min-width="90px" align="center">
+          <el-table-column label="比例 (%)" prop="threerate" min-width="90px" align="center" />
+          <el-table-column label="重量 (g)" prop="threeweight" min-width="90px" align="center" />
+        </el-table-column>
+    
+      </el-table>
+      <Pagination v-show="table.total>0" :total="table.total" :page.sync="table.getdataListParm.offset" :limit.sync="table.getdataListParm.pagecount" @pagination="getList" />
+    </div>
+   
+  </div>
+</template>
+
+<script>
+import { GetDataByName } from '@/api/common'
+import draggable from 'vuedraggable'
+import Cookies from 'js-cookie'
+import { parseTime } from '@/utils/index.js'
+import Pagination from '@/components/Pagination'
+export default {
+  name: 'MaterialIssuancePlan',
+  display: 'Two list header slot',
+  order: 14,
+  components: { Pagination },
+  data() {
+    return {
+      table: {
+        getdataListParm: {
+          name: 'getDungHistory',
+          page: 1,
+          offset: 1,
+          pagecount: 12,
+          returntype: 'Map',
+          parammaps: {
+            pastureid: Cookies.get('pastureid'),
+            operatetime: ''
+          }
+        },
+        list: [],
+        total: 0,
+        tableKey: 0,
+        listLoading: false,
+        temp: {},
+        changeList: [],
+        startObj: {}
+      },
+
+      textMap: {
+        seeHistory: '粪便筛修改记录'
+      },
+      seeHistory: {
+        dialogFormVisible: false, dialogStatus: '',
+        total: 0, tableKey: 0, listLoading: false,
+        getdataListParm: {
+          name: 'getDungHistoryBar', page: 1, offset: 1, pagecount: 10, returntype: 'Map',
+          parammaps: {
+            pastureid: Cookies.get('pastureid'),
+            barid: '',
+            inputDatetime: '',
+            time1: '',
+            time2: ''
+          }
+        }
+      },
+
+      rowStyle: { maxHeight: 30 + 'px', height: 30 + 'px' },
+      cellStyle: { padding: 0 + 'px' }
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    changeDate() {
+      this.getList()
+    },
+    getList() {
+      this.table.listLoading = true
+      GetDataByName(this.table.getdataListParm).then(response => {
+        console.log('table数据', response.data.list)
+        if (response.data.list !== null) {
+          this.table.list = response.data.list
+          this.table.pageNum = response.data.pageNum
+          this.table.pageSize = response.data.pageSize
+          this.table.total = response.data.total
+        } else {
+          this.table.list = []
+        }
+        setTimeout(() => {
+          this.table.listLoading = false
+        }, 100)
+      })
+    },
+
+    handleSearch() {
+      if (this.table.getdataListParm.parammaps.operatetime == '' || this.table.getdataListParm.parammaps.operatetime == null ) {
+        this.table.getdataListParm.parammaps.operatetime = ''
+      } else {
+        this.table.getdataListParm.parammaps.operatetime = parseTime(this.table.getdataListParm.parammaps.operatetime, '{y}-{m}-{d}')
+      }
+      this.getList()
+    },
+    handleRefresh() {
+      this.table.getdataListParm.parammaps.operatetime = ''
+      this.getList()
+    },
+   
+    
+  }
+}
+</script>
+
+<style  lang="scss" scoped>
+ .search{margin-bottom: 10px;}
+</style>

+ 99 - 0
src/components/Encapsulation/index.vue

@@ -0,0 +1,99 @@
+<template>
+  <div id="app">
+    <div class="content">
+      <div class="data-container" style="width:98%;margin:0 auto;">
+        <h3>各牧场设备统计表:</h3>
+        <el-table ref="interfaceTable" :data="dataList" border :row-style="rowStyle" :cell-style="cellStyle" style="width: 100%" :span-method="colspanMethod" :show-header="showHeader">
+          <el-table-column label="一级分类" prop="pasture" align="center" width="160" />
+          <el-table-column label="二级分类" prop="pasture1" align="center" />
+          <el-table-column label="三级分类" prop="pasture2" align="center" width="160" />
+          <el-table-column label="类型" prop="type" align="center" />
+          <el-table-column label="宝鸡1" prop="pastureName1" align="center" />
+          <el-table-column label="宝鸡2" prop="pastureName2" align="center" width="160" />
+          <!-- <el-table-column label="物流公司" prop="companyName" align="center" />
+          <el-table-column label="物流单号" prop="logisticsNo" align="center" width="160" />
+          <el-table-column label="发货时间" prop="deliveryTime" align="center" width="140" />
+          <el-table-column label="包裹信息" align="center" prop="arr">
+            <template slot-scope="scope">
+              <div v-if="scope.row.packageLong">
+                <div v-for="(item, index) in scope.row.arr" :key="index">{{ item.msg }}</div>
+              </div>
+              <div v-else>/</div>
+            </template>
+          </el-table-column>
+          <el-table-column label="包材编号" prop="materialsCode" align="center" /> -->
+        </el-table>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import datas from '../../data.js'
+import { handleTableSpan, handleObjectSpanMethod } from '../../util.js'
+export default {
+  components: {},
+  mixins: [],
+  data() {
+    return {
+      border: false,
+      showHeader: false,
+      dataList: [],
+      // 要合并的单元格的rowspan 数据
+      rowspanObj: {},
+      // 要纵向合并的单元格的key数组
+      mergekeys: ['pasture', 'pasture1', 'pasture2', 'logisticsNo', 'arr', 'materialsCode'],
+      rowStyle: { maxHeight: 30 + 'px', height: 30 + 'px' },
+      cellStyle: { padding: 0 + 'px' }
+    }
+  },
+  computed: {},
+  watch: {
+    dataList: function() {
+      this.$nextTick(function() {
+        this.$refs.interfaceTable.$el.background = 'red !important'
+        console.log(this.$refs.interfaceTable.$el)
+        console.log(this.$refs.interfaceTable)
+      })
+    }
+  },
+  created() {},
+  mounted() {
+    this.getDataList()
+  },
+  methods: {
+    getDataList() {
+      this.dataList = datas
+      console.log()
+
+      // 先处理一下数据,拿到要合并单元格的 rowspan 数据
+      this.rowspanObj = handleTableSpan(this.mergekeys, this.dataList)
+      console.log(this.rowspanObj)
+      // const length = 'mm'
+      // const weight = 'g'
+      // const arr = []
+
+      // datas.forEach((element, index) => {
+      //   element.arr = [
+      //     { msg: '长:' + element.packageLong + `${length}` },
+      //     { msg: '宽:' + element.packageWidth + `${length}` },
+      //     { msg: '高:' + element.packageHeight + `${length}` },
+      //     { msg: '重量:' + element.packageWeight + `${weight}` }
+      //   ]
+      //   element.expressPackCode = element.expressPackCode ? element.expressPackCode : '/'
+      //   element.companyName = element.companyName ? element.companyName : '/'
+      //   element.logisticsNo = element.logisticsNo ? element.logisticsNo : '/'
+      //   element.deliveryTime = element.deliveryTime ? element.deliveryTime : '/'
+      //   element.logisticsNo = element.logisticsNo ? element.logisticsNo : '/'
+      //   element.materialsCode = element.materialsCode ? element.materialsCode : '/'
+      // })
+    },
+    colspanMethod(tableObj) {
+      return handleObjectSpanMethod(tableObj, this.mergekeys, this.rowspanObj, true)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 54 - 0
src/components/GithubCorner/index.vue

@@ -0,0 +1,54 @@
+<template>
+  <a href="https://github.com/PanJiaChen/vue-element-admin" target="_blank" class="github-corner" aria-label="View source on Github">
+    <svg
+      width="80"
+      height="80"
+      viewBox="0 0 250 250"
+      style="fill:#40c9c6; color:#fff;"
+      aria-hidden="true"
+    >
+      <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" />
+      <path
+        d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
+        fill="currentColor"
+        style="transform-origin: 130px 106px;"
+        class="octo-arm"
+      />
+      <path
+        d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
+        fill="currentColor"
+        class="octo-body"
+      />
+    </svg>
+  </a>
+</template>
+
+<style scoped>
+.github-corner:hover .octo-arm {
+  animation: octocat-wave 560ms ease-in-out
+}
+
+@keyframes octocat-wave {
+  0%,
+  100% {
+    transform: rotate(0)
+  }
+  20%,
+  60% {
+    transform: rotate(-25deg)
+  }
+  40%,
+  80% {
+    transform: rotate(10deg)
+  }
+}
+
+@media (max-width:500px) {
+  .github-corner:hover .octo-arm {
+    animation: none
+  }
+  .github-corner .octo-arm {
+    animation: octocat-wave 560ms ease-in-out
+  }
+}
+</style>

+ 45 - 0
src/components/Hamburger/index.vue

@@ -0,0 +1,45 @@
+<template>
+  <div style="padding: 0 15px;" @click="toggleClick">
+    <svg
+      :class="{'is-active':isActive}"
+      class="hamburger"
+      viewBox="0 0 1024 1024"
+      xmlns="http://www.w3.org/2000/svg"
+      width="64"
+      height="64"
+    >
+      <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" fill="#ffffff" />
+    </svg>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Hamburger',
+  props: {
+    isActive: {
+      type: Boolean,
+      default: false
+    }
+  },
+  methods: {
+    toggleClick() {
+      this.$emit('toggleClick')
+    }
+  }
+}
+</script>
+
+<style scoped>
+.hamburger {
+  display: inline-block;
+  vertical-align: middle;
+  width: 20px;
+  height: 20px;
+  color: #fff !important;
+}
+
+.hamburger.is-active {
+  transform: rotate(180deg);
+}
+</style>

+ 180 - 0
src/components/HeaderSearch/index.vue

@@ -0,0 +1,180 @@
+<template>
+  <div :class="{'show':show}" class="header-search">
+    <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
+    <el-select
+      ref="headerSearchSelect"
+      v-model="search"
+      :remote-method="querySearch"
+      filterable
+      default-first-option
+      remote
+      placeholder="输入设备编号或名称"
+      class="header-search-select"
+      @change="change"
+    >
+      <el-option v-for="item in options" :key="item.path" :value="item" :label="item.title.join(' > ')" />
+    </el-select>
+  </div>
+</template>
+
+<script>
+// fuse is a lightweight fuzzy-search module
+// make search results more in line with expectations
+import Fuse from 'fuse.js'
+import path from 'path'
+
+export default {
+  name: 'HeaderSearch',
+  data() {
+    return {
+      search: '',
+      options: [],
+      searchPool: [],
+      show: false,
+      fuse: undefined
+    }
+  },
+  computed: {
+    routes() {
+      return this.$store.getters.permission_routes
+    }
+  },
+  watch: {
+    routes() {
+      this.searchPool = this.generateRoutes(this.routes)
+    },
+    searchPool(list) {
+      this.initFuse(list)
+    },
+    show(value) {
+      if (value) {
+        document.body.addEventListener('click', this.close)
+      } else {
+        document.body.removeEventListener('click', this.close)
+      }
+    }
+  },
+  mounted() {
+    this.searchPool = this.generateRoutes(this.routes)
+  },
+  methods: {
+    click() {
+      this.show = !this.show
+      if (this.show) {
+        this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
+      }
+    },
+    close() {
+      this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
+      this.options = []
+      this.show = false
+    },
+    change(val) {
+      this.$router.push(val.path)
+      this.search = ''
+      this.options = []
+      this.$nextTick(() => {
+        this.show = false
+      })
+    },
+    initFuse(list) {
+      this.fuse = new Fuse(list, {
+        shouldSort: true,
+        threshold: 0.4,
+        location: 0,
+        distance: 100,
+        maxPatternLength: 32,
+        minMatchCharLength: 1,
+        keys: [{
+          name: 'title',
+          weight: 0.7
+        }, {
+          name: 'path',
+          weight: 0.3
+        }]
+      })
+    },
+    // Filter out the routes that can be displayed in the sidebar
+    // And generate the internationalized title
+    generateRoutes(routes, basePath = '/', prefixTitle = []) {
+      let res = []
+
+      for (const router of routes) {
+        // skip hidden router
+        if (router.hidden) { continue }
+
+        const data = {
+          path: path.resolve(basePath, router.path),
+          title: [...prefixTitle]
+        }
+
+        if (router.meta && router.meta.title) {
+          data.title = [...data.title, router.meta.title]
+
+          if (router.redirect !== 'noRedirect') {
+            // only push the routes with title
+            // special case: need to exclude parent router without redirect
+            res.push(data)
+          }
+        }
+
+        // recursive child routes
+        if (router.children) {
+          const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
+          if (tempRoutes.length >= 1) {
+            res = [...res, ...tempRoutes]
+          }
+        }
+      }
+      return res
+    },
+    querySearch(query) {
+      if (query !== '') {
+        this.options = this.fuse.search(query)
+      } else {
+        this.options = []
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.header-search {
+  font-size: 0 !important;
+
+  .search-icon {
+    cursor: pointer;
+    font-size: 18px;
+    vertical-align: middle;
+  }
+
+  .header-search-select {
+    font-size: 18px;
+    transition: width 0.2s;
+    width: 0;
+    overflow: hidden;
+    background: transparent;
+    border-radius: 0;
+    display: inline-block;
+    vertical-align: middle;
+
+    /deep/ .el-input__inner {
+      border-radius: 0;
+      border: 0;
+      padding-left: 0;
+      padding-right: 0;
+      box-shadow: none !important;
+      border-bottom: 1px solid #d9d9d9;
+      vertical-align: middle;
+    }
+  }
+
+  &.show {
+    .header-search-select {
+      width: 210px;
+      margin-left: 10px;
+    }
+  }
+}
+</style>

+ 35 - 0
src/components/InputGroup/index.vue

@@ -0,0 +1,35 @@
+<template>
+  <div class="text_group">
+    <div class="input_group" :class="{'is-invalid': error}">
+      <!-- 输入框 -->
+      <input
+        :type="type"
+        :placeholder="placeholder"
+        :value="value"
+        :name="name"
+        @input="$emit('input',$event.target.value)"
+      >
+      <!-- 输入框后面的内容 -->
+      <button v-if="btnTitle" :disabled="disabled" @click="$emit('btnClick')">{{ btnTitle }}</button>
+    </div>
+    <!-- 验证提示 -->
+    <div v-if="error" class="invalid-feedback">{{ error }}</div>
+  </div>
+</template>
+<script>
+export default {
+  name: 'InputGroup',
+  props: {
+    type: {
+      type: String,
+      default: 'text'
+    },
+    placeholder: String,
+    value: String,
+    name: String,
+    disabled: Boolean,
+    btnTitle: String, // input框中的文字
+    error: String // 验证不正确提示
+  }
+}
+</script>

+ 103 - 0
src/components/Pagination/index.vue

@@ -0,0 +1,103 @@
+<template>
+  <div :class="{'hidden':hidden}" class="pagination-container">
+    <el-pagination
+      ref="pagination"
+      :background="background"
+      :current-page.sync="currentPage"
+      :page-size.sync="pageSize"
+      :layout="layout"
+      :page-sizes="pageSizes"
+      :total="total"
+      v-bind="$attrs"
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+    />
+  </div>
+</template>
+
+<script>
+import { scrollTo } from '@/utils/scroll-to'
+
+export default {
+  name: 'Pagination',
+  props: {
+    total: {
+      required: true,
+      type: Number
+    },
+    page: {
+      type: Number,
+      default: 1
+    },
+    limit: {
+      type: Number,
+      default: 10
+    },
+    pageSizes: {
+      type: Array,
+      default() {
+        return [10, 20, 30, 50, 100]
+        // return [50, 30, 20, 10]
+      }
+    },
+    layout: {
+      type: String,
+      default: 'total, sizes, prev, pager, next, jumper'
+    },
+    background: {
+      type: Boolean,
+      default: true
+    },
+    autoScroll: {
+      type: Boolean,
+      default: true
+    },
+    hidden: {
+      type: Boolean,
+      default: false
+    }
+  },
+  computed: {
+    currentPage: {
+      get() {
+        return this.page
+      },
+      set(val) {
+        this.$emit('update:page', val)
+      }
+    },
+    pageSize: {
+      get() {
+        return this.limit
+      },
+      set(val) {
+        this.$emit('update:limit', val)
+      }
+    }
+  },
+  methods: {
+    handleSizeChange(val) {
+      this.$emit('pagination', { page: this.currentPage, limit: val })
+      if (this.autoScroll) {
+        scrollTo(0, 800)
+      }
+    },
+    handleCurrentChange(val) {
+      this.$emit('pagination', { page: val, limit: this.pageSize })
+      if (this.autoScroll) {
+        scrollTo(0, 800)
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.pagination-container {
+  background: #fff;
+  padding: 16px 16px;
+}
+.pagination-container.hidden {
+  display: none;
+}
+</style>

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません