소스 검색

first commit

Jay 7 달 전
커밋
2ca9fdaaa9
100개의 변경된 파일4477개의 추가작업 그리고 0개의 파일을 삭제
  1. 14 0
      .editorconfig
  2. 5 0
      .env.development
  3. 6 0
      .env.production
  4. 8 0
      .env.staging
  5. 4 0
      .eslintignore
  6. 198 0
      .eslintrc.js
  7. 16 0
      .gitignore
  8. 5 0
      .travis.yml
  9. 21 0
      LICENSE
  10. 107 0
      README-zh.md
  11. 98 0
      README.md
  12. 14 0
      babel.config.js
  13. 24 0
      jest.config.js
  14. 9 0
      jsconfig.json
  15. 69 0
      package.json
  16. 8 0
      postcss.config.js
  17. BIN
      public/favicon.ico
  18. BIN
      public/images/bg1.png
  19. BIN
      public/images/bg10.jpg
  20. BIN
      public/images/bg2.png
  21. BIN
      public/images/bg3.png
  22. BIN
      public/images/bg4.jpg
  23. BIN
      public/images/bg5.jpg
  24. BIN
      public/images/bg6.jpg
  25. BIN
      public/images/bg7.jpg
  26. BIN
      public/images/bg8.jpg
  27. BIN
      public/images/bg9.jpg
  28. 17 0
      public/index.html
  29. 11 0
      src/App.vue
  30. 30 0
      src/api/market/apilog.js
  31. 19 0
      src/api/market/apimapping.js
  32. 46 0
      src/api/market/apimask.js
  33. 98 0
      src/api/market/dataapi.js
  34. 53 0
      src/api/market/dataservice.js
  35. 30 0
      src/api/market/dataservicelog.js
  36. 41 0
      src/api/masterdata/datamanage.js
  37. 89 0
      src/api/masterdata/datamodel.js
  38. 46 0
      src/api/metadata/changerecord.js
  39. 24 0
      src/api/metadata/dataauthorize.js
  40. 62 0
      src/api/metadata/datacolumn.js
  41. 107 0
      src/api/metadata/datasource.js
  42. 54 0
      src/api/metadata/datatable.js
  43. 17 0
      src/api/metadata/sqlconsole.js
  44. 30 0
      src/api/monitor/loginlog.js
  45. 30 0
      src/api/monitor/operlog.js
  46. 23 0
      src/api/quality/checkjob.js
  47. 9 0
      src/api/quality/checklog.js
  48. 41 0
      src/api/quality/checkreport.js
  49. 70 0
      src/api/quality/checkrule.js
  50. 68 0
      src/api/scheduler/job.js
  51. 30 0
      src/api/scheduler/log.js
  52. 40 0
      src/api/standard/contrast.js
  53. 46 0
      src/api/standard/contrastdict.js
  54. 84 0
      src/api/standard/datadict.js
  55. 30 0
      src/api/standard/dictmapping.js
  56. 62 0
      src/api/system/config.js
  57. 46 0
      src/api/system/dept.js
  58. 107 0
      src/api/system/dict.js
  59. 54 0
      src/api/system/menu.js
  60. 54 0
      src/api/system/post.js
  61. 54 0
      src/api/system/role.js
  62. 108 0
      src/api/system/user.js
  63. 54 0
      src/api/visual/databoard.js
  64. 73 0
      src/api/visual/datachart.js
  65. 54 0
      src/api/visual/datascreen.js
  66. 62 0
      src/api/visual/dataset.js
  67. 46 0
      src/api/workflow/business.js
  68. 81 0
      src/api/workflow/definition.js
  69. 55 0
      src/api/workflow/instance.js
  70. 25 0
      src/api/workflow/task.js
  71. BIN
      src/assets/401_images/401.gif
  72. BIN
      src/assets/404_images/404.png
  73. BIN
      src/assets/404_images/404_cloud.png
  74. 3 0
      src/assets/icons/iconfont.css
  75. BIN
      src/assets/icons/iconfont.eot
  76. 0 0
      src/assets/icons/iconfont.js
  77. 471 0
      src/assets/icons/iconfont.json
  78. 22 0
      src/assets/icons/iconfont.svg
  79. BIN
      src/assets/icons/iconfont.ttf
  80. BIN
      src/assets/icons/iconfont.woff
  81. BIN
      src/assets/icons/iconfont.woff2
  82. BIN
      src/assets/images/login-bg.jpg
  83. 79 0
      src/components/Breadcrumb/index.vue
  84. 44 0
      src/components/Hamburger/index.vue
  85. 544 0
      src/components/PivotTable/index.vue
  86. 60 0
      src/components/Screenfull/index.vue
  87. 110 0
      src/components/SqlEditor/index.vue
  88. 62 0
      src/components/SvgIcon/index.vue
  89. 175 0
      src/components/ThemePicker/index.vue
  90. 16 0
      src/directive/flow/flowDel.js
  91. 16 0
      src/directive/flow/flowEdit.js
  92. 15 0
      src/directive/flow/index.js
  93. 23 0
      src/directive/permission/hasPerm.js
  94. 23 0
      src/directive/permission/hasRole.js
  95. 15 0
      src/directive/permission/index.js
  96. 9 0
      src/icons/index.js
  97. 1 0
      src/icons/svg/chart_bar.svg
  98. 1 0
      src/icons/svg/chart_bar_active.svg
  99. 1 0
      src/icons/svg/chart_donut.svg
  100. 1 0
      src/icons/svg/chart_donut_active.svg

+ 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

+ 5 - 0
.env.development

@@ -0,0 +1,5 @@
+# just a flag
+ENV = 'development'
+
+# base api
+VUE_APP_BASE_API = '/dev-api'

+ 6 - 0
.env.production

@@ -0,0 +1,6 @@
+# just a flag
+ENV = 'production'
+
+# base api
+VUE_APP_BASE_API = '/prod-api'
+

+ 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

+ 198 - 0
.eslintrc.js

@@ -0,0 +1,198 @@
+module.exports = {
+  root: true,
+  parserOptions: {
+    parser: 'babel-eslint',
+    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

+ 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.

+ 107 - 0
README-zh.md

@@ -0,0 +1,107 @@
+# 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)
+
+## GitAds
+
+[<img src="https://images.gitads.io/PanJiaChen/vue-admin-template" alt="GitAds" />](https://tracking.gitads.io/?repo=PanJiaChen/vue-admin-template)
+
+
+## 相关项目
+
+- [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)
+
+- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
+
+写了一个系列的教程配套文章,如何从零构建后一个完整的后台项目:
+
+- [手摸手,带你用 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/)
+
+## 购买贴纸
+
+你也可以通过 购买[官方授权的贴纸](https://smallsticker.com/product/vue-element-admin) 的方式来支持 vue-element-admin - 每售出一张贴纸,我们将获得 2 元的捐赠。
+
+## 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

+ 98 - 0
README.md

@@ -0,0 +1,98 @@
+# 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`**
+
+
+## GitAds
+
+> vue-admin-template is being sponsored by the following tool; please help to support us by taking a look and signing up to a free trial
+
+[<img src="https://images.gitads.io/vue-admin-template" alt="GitAds" />](https://tracking.gitads.io/?repo=vue-admin-template)
+
+
+## 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)
+
+- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
+
+## 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

+ 14 - 0
babel.config.js

@@ -0,0 +1,14 @@
+module.exports = {
+  presets: [
+    // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
+    '@vue/cli-plugin-babel/preset'
+  ],
+  'env': {
+    'development': {
+      // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
+      // This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
+      // https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html
+      'plugins': ['dynamic-import-node']
+    }
+  }
+}

+ 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/'
+}

+ 9 - 0
jsconfig.json

@@ -0,0 +1,9 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./",
+    "paths": {
+        "@/*": ["src/*"]
+    }
+  },
+  "exclude": ["node_modules", "dist"]
+}

+ 69 - 0
package.json

@@ -0,0 +1,69 @@
+{
+  "name": "datax-ui",
+  "version": "1.0.0",
+  "description": "A vue admin template with Element UI & axios & iconfont & permission control & lint",
+  "author": "YuWei",
+  "scripts": {
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "lint": "vue-cli-service lint"
+  },
+  "dependencies": {
+    "@riophae/vue-treeselect": "^0.4.0",
+    "axios": "0.18.1",
+    "core-js": "3.6.5",
+    "echarts": "^4.8.0",
+    "echarts-liquidfill": "^2.0.6",
+    "echarts-wordcloud": "^1.1.3",
+    "element-ui": "2.13.2",
+    "good-storage": "^1.1.1",
+    "jsplumb": "^2.14.6",
+    "moment": "^2.29.1",
+    "normalize.css": "7.0.0",
+    "nprogress": "0.2.0",
+    "path-to-regexp": "2.4.0",
+    "screenfull": "^5.0.2",
+    "sql-formatter": "^2.3.3",
+    "vue": "2.6.10",
+    "vue-codemirror": "^4.0.6",
+    "vue-draggable-resizable-gorkys": "^2.4.4",
+    "vue-grid-layout": "^2.3.11",
+    "vue-router": "3.0.6",
+    "vue2-editor": "^2.10.2",
+    "vuedraggable": "^2.24.0",
+    "vuex": "3.1.0"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "4.4.4",
+    "@vue/cli-plugin-eslint": "4.4.4",
+    "@vue/cli-plugin-unit-jest": "4.4.4",
+    "@vue/cli-service": "4.4.4",
+    "@vue/test-utils": "1.0.0-beta.29",
+    "autoprefixer": "9.5.1",
+    "babel-eslint": "10.1.0",
+    "babel-jest": "23.6.0",
+    "babel-plugin-dynamic-import-node": "2.3.3",
+    "chalk": "2.4.2",
+    "connect": "3.6.6",
+    "eslint": "6.7.2",
+    "eslint-plugin-vue": "6.2.2",
+    "html-webpack-plugin": "3.2.0",
+    "runjs": "4.3.2",
+    "sass": "1.26.8",
+    "sass-loader": "8.0.2",
+    "script-ext-html-webpack-plugin": "2.1.3",
+    "serve-static": "1.13.2",
+    "svg-sprite-loader": "4.1.3",
+    "svgo": "1.2.2",
+    "vue-template-compiler": "2.6.10"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions"
+  ],
+  "engines": {
+    "node": ">=8.9",
+    "npm": ">= 3.0.0"
+  },
+  "license": "MIT"
+}

+ 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


BIN
public/images/bg1.png


BIN
public/images/bg10.jpg


BIN
public/images/bg2.png


BIN
public/images/bg3.png


BIN
public/images/bg4.jpg


BIN
public/images/bg5.jpg


BIN
public/images/bg6.jpg


BIN
public/images/bg7.jpg


BIN
public/images/bg8.jpg


BIN
public/images/bg9.jpg


+ 17 - 0
public/index.html

@@ -0,0 +1,17 @@
+<!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">
+    <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>
+</html>

+ 11 - 0
src/App.vue

@@ -0,0 +1,11 @@
+<template>
+  <div id="app">
+    <router-view />
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'App'
+}
+</script>

+ 30 - 0
src/api/market/apilog.js

@@ -0,0 +1,30 @@
+import request from '@/utils/request'
+
+export function pageApiLog(data) {
+  return request({
+    url: '/data/api/apiLogs/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getApiLog(id) {
+  return request({
+    url: '/data/api/apiLogs/' + id,
+    method: 'get'
+  })
+}
+
+export function delApiLog(id) {
+  return request({
+    url: '/data/api/apiLogs/' + id,
+    method: 'delete'
+  })
+}
+
+export function delApiLogs(ids) {
+  return request({
+    url: '/data/api/apiLogs/batch/' + ids,
+    method: 'delete'
+  })
+}

+ 19 - 0
src/api/market/apimapping.js

@@ -0,0 +1,19 @@
+import request from '@/utils/request'
+
+export function getApiCall(url, header, data) {
+  return request({
+    url: '/data/api/' + url,
+    method: 'get',
+    headers: header,
+    params: data
+  })
+}
+
+export function postApiCall(url, header, data) {
+  return request({
+    url: '/data/api/' + url,
+    method: 'post',
+    headers: header,
+    data: data
+  })
+}

+ 46 - 0
src/api/market/apimask.js

@@ -0,0 +1,46 @@
+import request from '@/utils/request'
+
+export function pageApiMask (data) {
+  return request({
+    url: '/data/market/apiMasks/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getApiMask (id) {
+  return request({
+    url: '/data/market/apiMasks/' + id,
+    method: 'get'
+  })
+}
+
+export function delApiMask (id) {
+  return request({
+    url: '/data/market/apiMasks/' + id,
+    method: 'delete'
+  })
+}
+
+export function delApiMasks (ids) {
+  return request({
+    url: '/data/market/apiMasks/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addApiMask (data) {
+  return request({
+    url: '/data/market/apiMasks',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateApiMask (data) {
+  return request({
+    url: '/data/market/apiMasks/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 98 - 0
src/api/market/dataapi.js

@@ -0,0 +1,98 @@
+import request from '@/utils/request'
+
+export function listDataApi(data) {
+  return request({
+    url: '/data/market/dataApis/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pageDataApi(data) {
+  return request({
+    url: '/data/market/dataApis/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDataApi(id) {
+  return request({
+    url: '/data/market/dataApis/' + id,
+    method: 'get'
+  })
+}
+
+export function delDataApi(id) {
+  return request({
+    url: '/data/market/dataApis/' + id,
+    method: 'delete'
+  })
+}
+
+export function delDataApis(ids) {
+  return request({
+    url: '/data/market/dataApis/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addDataApi(data) {
+  return request({
+    url: '/data/market/dataApis',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDataApi(data) {
+  return request({
+    url: '/data/market/dataApis/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function sqlParse(data) {
+  return request({
+    url: '/data/market/dataApis/sql/parse',
+    method: 'post',
+    data: data
+  })
+}
+
+export function copyDataApi(id) {
+  return request({
+    url: '/data/market/dataApis/' + id + '/copy',
+    method: 'post'
+  })
+}
+
+export function releaseDataApi(id) {
+  return request({
+    url: '/data/market/dataApis/' + id + '/release',
+    method: 'post'
+  })
+}
+
+export function cancelDataApi(id) {
+  return request({
+    url: '/data/market/dataApis/' + id + '/cancel',
+    method: 'post'
+  })
+}
+
+export function word(id) {
+  return request({
+    url: '/data/market/dataApis/word/' + id,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+
+export function getDataApiDetail(id) {
+  return request({
+    url: '/data/market/dataApis/detail/' + id,
+    method: 'get'
+  })
+}

+ 53 - 0
src/api/market/dataservice.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+export function pageDataService(data) {
+  return request({
+    url: '/data/service/services/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDataService(id) {
+  return request({
+    url: `/data/service/services/${id}`,
+    method: 'get'
+  })
+}
+
+export function delDataService(id) {
+  return request({
+    url: `/data/service/services/${id}`,
+    method: 'delete'
+  })
+}
+
+export function delDataServices(ids) {
+  return request({
+    url: `/data/service/services/batch/${ids}`,
+    method: 'delete'
+  })
+}
+
+export function addDataService(data) {
+  return request({
+    url: '/data/service/services',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDataService(data) {
+  return request({
+    url: `/data/service/services/${data.id}`,
+    method: 'put',
+    data: data
+  })
+}
+
+export function getDataServiceDetail(id) {
+  return request({
+    url: `/data/service/services/detail/${id}`,
+    method: 'get'
+  })
+}

+ 30 - 0
src/api/market/dataservicelog.js

@@ -0,0 +1,30 @@
+import request from '@/utils/request'
+
+export function pageDataServiceLog(data) {
+  return request({
+    url: '/data/service/serviceLogs/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDataServiceLog(id) {
+  return request({
+    url: '/data/service/serviceLogs/' + id,
+    method: 'get'
+  })
+}
+
+export function delDataServiceLog(id) {
+  return request({
+    url: '/data/service/serviceLogs/' + id,
+    method: 'delete'
+  })
+}
+
+export function delDataServiceLogs(ids) {
+  return request({
+    url: '/data/service/serviceLogs/batch/' + ids,
+    method: 'delete'
+  })
+}

+ 41 - 0
src/api/masterdata/datamanage.js

@@ -0,0 +1,41 @@
+import request from '@/utils/request'
+
+export function pageData(data) {
+  return request({
+    url: '/data/masterdata/datas/page',
+    method: 'post',
+    data: data
+  })
+}
+
+export function getData(data) {
+  return request({
+    url: '/data/masterdata/datas/' + data.id,
+    method: 'get',
+    params: data
+  })
+}
+
+export function addData(data) {
+  return request({
+    url: '/data/masterdata/datas/addData',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateData(data) {
+  return request({
+    url: '/data/masterdata/datas/updateData/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function delData(data) {
+  return request({
+    url: '/data/masterdata/datas/delData/' + data.id,
+    method: 'post',
+    data: data
+  })
+}

+ 89 - 0
src/api/masterdata/datamodel.js

@@ -0,0 +1,89 @@
+import request from '@/utils/request'
+
+export function listDataModel(data) {
+  return request({
+    url: '/data/masterdata/models/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pageDataModel(data) {
+  return request({
+    url: '/data/masterdata/models/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDataModel(id) {
+  return request({
+    url: '/data/masterdata/models/' + id,
+    method: 'get'
+  })
+}
+
+export function delDataModel(id) {
+  return request({
+    url: '/data/masterdata/models/' + id,
+    method: 'delete'
+  })
+}
+
+export function delDataModels(ids) {
+  return request({
+    url: '/data/masterdata/models/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addDataModel(data) {
+  return request({
+    url: '/data/masterdata/models',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDataModel(data) {
+  return request({
+    url: '/data/masterdata/models/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function submitDataModel(id) {
+  return request({
+    url: '/data/masterdata/models/submit/' + id,
+    method: 'post'
+  })
+}
+
+export function createTable(id) {
+  return request({
+    url: '/data/masterdata/models/table/create/' + id,
+    method: 'post'
+  })
+}
+
+export function dropTable(id) {
+  return request({
+    url: '/data/masterdata/models/table/drop/' + id,
+    method: 'delete'
+  })
+}
+
+export function getTableParam(id) {
+  return request({
+    url: '/data/masterdata/models/table/param/' + id,
+    method: 'get'
+  })
+}
+
+export function getFormParam(id) {
+  return request({
+    url: '/data/masterdata/models/form/param/' + id,
+    method: 'get'
+  })
+}

+ 46 - 0
src/api/metadata/changerecord.js

@@ -0,0 +1,46 @@
+import request from '@/utils/request'
+
+export function pageChangeRecord (data) {
+  return request({
+    url: '/data/metadata/changeRecords/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getChangeRecord (id) {
+  return request({
+    url: '/data/metadata/changeRecords/' + id,
+    method: 'get'
+  })
+}
+
+export function delChangeRecord (id) {
+  return request({
+    url: '/data/metadata/changeRecords/' + id,
+    method: 'delete'
+  })
+}
+
+export function delChangeRecords (ids) {
+  return request({
+    url: '/data/metadata/changeRecords/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addChangeRecord (data) {
+  return request({
+    url: '/data/metadata/changeRecords',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateChangeRecord (data) {
+  return request({
+    url: '/data/metadata/changeRecords/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 24 - 0
src/api/metadata/dataauthorize.js

@@ -0,0 +1,24 @@
+import request from '@/utils/request'
+
+// 刷新参数缓存
+export function refreshAuthorize() {
+  return request({
+    url: '/data/metadata/authorizes/refresh',
+    method: 'get'
+  })
+}
+
+export function getAuthorizedMetadata(id) {
+  return request({
+    url: '/data/metadata/authorizes/getAuthorizedMetadata/' + id,
+    method: 'get'
+  })
+}
+
+export function metadataAuthorize(data) {
+  return request({
+    url: '/data/metadata/authorizes/metadata',
+    method: 'post',
+    data: data
+  })
+}

+ 62 - 0
src/api/metadata/datacolumn.js

@@ -0,0 +1,62 @@
+import request from '@/utils/request'
+
+export function listDataColumn(data) {
+  return request({
+    url: '/data/metadata/columns/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pageDataColumn(data) {
+  return request({
+    url: '/data/metadata/columns/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDataColumn(id) {
+  return request({
+    url: '/data/metadata/columns/' + id,
+    method: 'get'
+  })
+}
+
+export function delDataColumn(id) {
+  return request({
+    url: '/data/metadata/columns/' + id,
+    method: 'delete'
+  })
+}
+
+export function delDataColumns(ids) {
+  return request({
+    url: '/data/metadata/columns/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addDataColumn(data) {
+  return request({
+    url: '/data/metadata/columns',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDataColumn(data) {
+  return request({
+    url: '/data/metadata/columns/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function getDataMetadataTree(level, data) {
+  return request({
+    url: '/data/metadata/columns/tree/' + level,
+    method: 'get',
+    params: data
+  })
+}

+ 107 - 0
src/api/metadata/datasource.js

@@ -0,0 +1,107 @@
+import request from '@/utils/request'
+
+// 刷新参数缓存
+export function refreshMetadata () {
+  return request({
+    url: '/data/metadata/sources/refresh',
+    method: 'get'
+  })
+}
+
+export function listDataSource (data) {
+  return request({
+    url: '/data/metadata/sources/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pageDataSource (data) {
+  return request({
+    url: '/data/metadata/sources/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDataSource (id) {
+  return request({
+    url: '/data/metadata/sources/' + id,
+    method: 'get'
+  })
+}
+
+export function delDataSource (id) {
+  return request({
+    url: '/data/metadata/sources/' + id,
+    method: 'delete'
+  })
+}
+
+export function delDataSources (ids) {
+  return request({
+    url: '/data/metadata/sources/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addDataSource (data) {
+  return request({
+    url: '/data/metadata/sources',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDataSource (data) {
+  return request({
+    url: '/data/metadata/sources/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function checkConnection (data) {
+  return request({
+    url: '/data/metadata/sources/checkConnection',
+    method: 'post',
+    data: data
+  })
+}
+
+export function queryByPage (data) {
+  return request({
+    url: '/data/metadata/sources/queryByPage',
+    method: 'post',
+    data: data
+  })
+}
+
+export function getDbTables (id) {
+  return request({
+    url: '/data/metadata/sources/' + id + '/tables',
+    method: 'get'
+  })
+}
+
+export function getDbTableColumns (id, tableName) {
+  return request({
+    url: '/data/metadata/sources/' + id + '/' + tableName + '/columns',
+    method: 'get'
+  })
+}
+
+export function sync (id) {
+  return request({
+    url: '/data/metadata/sources/sync/' + id,
+    method: 'post'
+  })
+}
+
+export function word (id) {
+  return request({
+    url: '/data/metadata/sources/word/' + id,
+    method: 'post',
+    responseType: 'blob'
+  })
+}

+ 54 - 0
src/api/metadata/datatable.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+export function listDataTable (data) {
+  return request({
+    url: '/data/metadata/tables/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pageDataTable (data) {
+  return request({
+    url: '/data/metadata/tables/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDataTable (id) {
+  return request({
+    url: '/data/metadata/tables/' + id,
+    method: 'get'
+  })
+}
+
+export function delDataTable (id) {
+  return request({
+    url: '/data/metadata/tables/' + id,
+    method: 'delete'
+  })
+}
+
+export function delDataTables (ids) {
+  return request({
+    url: '/data/metadata/tables/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addDataTable (data) {
+  return request({
+    url: '/data/metadata/tables',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDataTable (data) {
+  return request({
+    url: '/data/metadata/tables/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 17 - 0
src/api/metadata/sqlconsole.js

@@ -0,0 +1,17 @@
+import request from '@/utils/request'
+
+export function runSql (data) {
+  return request({
+    url: '/data/console/sql/run',
+    method: 'post',
+    data: data
+  })
+}
+
+export function stopSql (data) {
+  return request({
+    url: '/data/console/sql/stop',
+    method: 'post',
+    data: data
+  })
+}

+ 30 - 0
src/api/monitor/loginlog.js

@@ -0,0 +1,30 @@
+import request from '@/utils/request'
+
+export function pageLog (data) {
+  return request({
+    url: '/system/login/logs/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getLog (id) {
+  return request({
+    url: '/system/login/logs/' + id,
+    method: 'get'
+  })
+}
+
+export function delLog (id) {
+  return request({
+    url: '/system/login/logs/' + id,
+    method: 'delete'
+  })
+}
+
+export function delLogs (ids) {
+  return request({
+    url: '/system/login/logs/batch/' + ids,
+    method: 'delete'
+  })
+}

+ 30 - 0
src/api/monitor/operlog.js

@@ -0,0 +1,30 @@
+import request from '@/utils/request'
+
+export function pageLog (data) {
+  return request({
+    url: '/system/logs/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getLog (id) {
+  return request({
+    url: '/system/logs/' + id,
+    method: 'get'
+  })
+}
+
+export function delLog (id) {
+  return request({
+    url: '/system/logs/' + id,
+    method: 'delete'
+  })
+}
+
+export function delLogs (ids) {
+  return request({
+    url: '/system/logs/batch/' + ids,
+    method: 'delete'
+  })
+}

+ 23 - 0
src/api/quality/checkjob.js

@@ -0,0 +1,23 @@
+import request from '@/utils/request'
+
+export function pageCheckJob(data) {
+  return request({
+    url: '/data/quality/scheduleJobs/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pauseCheckJob(id) {
+  return request({
+    url: '/data/quality/scheduleJobs/pause/' + id,
+    method: 'post'
+  })
+}
+
+export function resumeCheckJob(id) {
+  return request({
+    url: '/data/quality/scheduleJobs/resume/' + id,
+    method: 'post'
+  })
+}

+ 9 - 0
src/api/quality/checklog.js

@@ -0,0 +1,9 @@
+import request from '@/utils/request'
+
+export function pageCheckLog(data) {
+  return request({
+    url: '/data/quality/scheduleLogs/page',
+    method: 'get',
+    params: data
+  })
+}

+ 41 - 0
src/api/quality/checkreport.js

@@ -0,0 +1,41 @@
+import request from '@/utils/request'
+
+export function listRuleType(data) {
+  return request({
+    url: '/data/quality/ruleTypes/report/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pageCheckReport(data) {
+  return request({
+    url: '/data/quality/checkReports/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getReportBySource(data) {
+  return request({
+    url: '/data/quality/checkReports/getReportBySource',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getReportByType(data) {
+  return request({
+    url: '/data/quality/checkReports/getReportByType',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getReportDetail(data) {
+  return request({
+    url: '/data/quality/checkReports/getReportDetail',
+    method: 'get',
+    params: data
+  })
+}

+ 70 - 0
src/api/quality/checkrule.js

@@ -0,0 +1,70 @@
+import request from '@/utils/request'
+
+export function listRuleType(data) {
+  return request({
+    url: '/data/quality/ruleTypes/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function listRuleItem(data) {
+  return request({
+    url: '/data/quality/ruleItems/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function listRuleLevel(data) {
+  return request({
+    url: '/data/quality/ruleLevels/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pageCheckRule(data) {
+  return request({
+    url: '/data/quality/checkRules/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getCheckRule(id) {
+  return request({
+    url: '/data/quality/checkRules/' + id,
+    method: 'get'
+  })
+}
+
+export function delCheckRule(id) {
+  return request({
+    url: '/data/quality/checkRules/' + id,
+    method: 'delete'
+  })
+}
+
+export function delCheckRules(ids) {
+  return request({
+    url: '/data/quality/checkRules/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addCheckRule(data) {
+  return request({
+    url: '/data/quality/checkRules',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateCheckRule(data) {
+  return request({
+    url: '/data/quality/checkRules/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 68 - 0
src/api/scheduler/job.js

@@ -0,0 +1,68 @@
+import request from '@/utils/request'
+
+export function listJob (data) {
+  return request({
+    url: '/quartz/jobs/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pageJob (data) {
+  return request({
+    url: '/quartz/jobs/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getJob (id) {
+  return request({
+    url: '/quartz/jobs/' + id,
+    method: 'get'
+  })
+}
+
+export function delJob (id) {
+  return request({
+    url: '/quartz/jobs/' + id,
+    method: 'delete'
+  })
+}
+
+export function addJob (data) {
+  return request({
+    url: '/quartz/jobs',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateJob (data) {
+  return request({
+    url: '/quartz/jobs/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function pauseJob (id) {
+  return request({
+    url: '/quartz/jobs/pause/' + id,
+    method: 'post'
+  })
+}
+
+export function resumeJob (id) {
+  return request({
+    url: '/quartz/jobs/resume/' + id,
+    method: 'post'
+  })
+}
+
+export function runJob (id) {
+  return request({
+    url: '/quartz/jobs/run/' + id,
+    method: 'post'
+  })
+}

+ 30 - 0
src/api/scheduler/log.js

@@ -0,0 +1,30 @@
+import request from '@/utils/request'
+
+export function pageLog (data) {
+  return request({
+    url: '/quartz/logs/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getLog (id) {
+  return request({
+    url: '/quartz/logs/' + id,
+    method: 'get'
+  })
+}
+
+export function delLog (id) {
+  return request({
+    url: '/quartz/logs/' + id,
+    method: 'delete'
+  })
+}
+
+export function delLogs (ids) {
+  return request({
+    url: '/quartz/logs/batch/' + ids,
+    method: 'delete'
+  })
+}

+ 40 - 0
src/api/standard/contrast.js

@@ -0,0 +1,40 @@
+import request from '@/utils/request'
+
+export function getContrastTree(data) {
+  return request({
+    url: '/data/standard/contrasts/tree',
+    method: 'get',
+    params: data
+  })
+}
+
+export function addContrast(data) {
+  return request({
+    url: '/data/standard/contrasts',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateContrast(data) {
+  return request({
+    url: '/data/standard/contrasts/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function delContrast(id) {
+  return request({
+    url: '/data/standard/contrasts/' + id,
+    method: 'delete'
+  })
+}
+
+export function contrastStat(data) {
+  return request({
+    url: '/data/standard/contrasts/stat',
+    method: 'get',
+    params: data
+  })
+}

+ 46 - 0
src/api/standard/contrastdict.js

@@ -0,0 +1,46 @@
+import request from '@/utils/request'
+
+export function pageContrastDict(data) {
+  return request({
+    url: '/data/standard/contrastDicts/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getContrastDict(id) {
+  return request({
+    url: '/data/standard/contrastDicts/' + id,
+    method: 'get'
+  })
+}
+
+export function delContrastDict(id) {
+  return request({
+    url: '/data/standard/contrastDicts/' + id,
+    method: 'delete'
+  })
+}
+
+export function delContrastDicts(ids) {
+  return request({
+    url: '/data/standard/contrastDicts/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addContrastDict(data) {
+  return request({
+    url: '/data/standard/contrastDicts',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateContrastDict(data) {
+  return request({
+    url: '/data/standard/contrastDicts/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 84 - 0
src/api/standard/datadict.js

@@ -0,0 +1,84 @@
+import request from '@/utils/request'
+
+export function refreshDict() {
+  return request({
+    url: '/data/standard/dicts/refresh',
+    method: 'get'
+  })
+}
+
+export function listDataDictType(data) {
+  return request({
+    url: '/data/standard/types/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function addDataDictType(data) {
+  return request({
+    url: '/data/standard/types',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDataDictType(data) {
+  return request({
+    url: '/data/standard/types/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function delDataDictType(id) {
+  return request({
+    url: '/data/standard/types/' + id,
+    method: 'delete'
+  })
+}
+
+export function pageDataDict(data) {
+  return request({
+    url: '/data/standard/dicts/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDataDict(id) {
+  return request({
+    url: '/data/standard/dicts/' + id,
+    method: 'get'
+  })
+}
+
+export function delDataDict(id) {
+  return request({
+    url: '/data/standard/dicts/' + id,
+    method: 'delete'
+  })
+}
+
+export function delDataDicts(ids) {
+  return request({
+    url: '/data/standard/dicts/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addDataDict(data) {
+  return request({
+    url: '/data/standard/dicts',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDataDict(data) {
+  return request({
+    url: '/data/standard/dicts/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 30 - 0
src/api/standard/dictmapping.js

@@ -0,0 +1,30 @@
+import request from '@/utils/request'
+
+export function getDictMapping(id) {
+  return request({
+    url: '/data/standard/mappings/' + id,
+    method: 'get'
+  })
+}
+
+export function dictAutoMapping(id) {
+  return request({
+    url: '/data/standard/mappings/auto/' + id,
+    method: 'post'
+  })
+}
+
+export function dictManualMapping(data) {
+  return request({
+    url: '/data/standard/mappings/manual',
+    method: 'post',
+    data: data
+  })
+}
+
+export function dictCancelMapping(id) {
+  return request({
+    url: '/data/standard/mappings/cancel/' + id,
+    method: 'post'
+  })
+}

+ 62 - 0
src/api/system/config.js

@@ -0,0 +1,62 @@
+import request from '@/utils/request'
+
+// 根据参数键名查询参数值
+export function getConfigKey (configKey) {
+  return request({
+    url: '/system/configs/key/' + configKey,
+    method: 'get'
+  })
+}
+
+// 刷新参数缓存
+export function refreshConfig () {
+  return request({
+    url: '/system/configs/refresh',
+    method: 'get'
+  })
+}
+
+export function pageConfig (data) {
+  return request({
+    url: '/system/configs/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getConfig (id) {
+  return request({
+    url: '/system/configs/' + id,
+    method: 'get'
+  })
+}
+
+export function delConfig (id) {
+  return request({
+    url: '/system/configs/' + id,
+    method: 'delete'
+  })
+}
+
+export function delConfigs (ids) {
+  return request({
+    url: '/system/configs/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addConfig (data) {
+  return request({
+    url: '/system/configs',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateConfig (data) {
+  return request({
+    url: '/system/configs/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 46 - 0
src/api/system/dept.js

@@ -0,0 +1,46 @@
+import request from '@/utils/request'
+
+export function listDept (data) {
+  return request({
+    url: '/system/depts/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDept (id) {
+  return request({
+    url: '/system/depts/' + id,
+    method: 'get'
+  })
+}
+
+export function delDept (id) {
+  return request({
+    url: '/system/depts/' + id,
+    method: 'delete'
+  })
+}
+
+export function delDepts (ids) {
+  return request({
+    url: '/system/depts/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addDept (data) {
+  return request({
+    url: '/system/depts',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDept (data) {
+  return request({
+    url: '/system/depts/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 107 - 0
src/api/system/dict.js

@@ -0,0 +1,107 @@
+import request from '@/utils/request'
+
+// 查询字典数据详细
+export function getDicts (dictCode) {
+  return request({
+    url: '/system/dicts/code/' + dictCode,
+    method: 'get'
+  })
+}
+
+// 刷新字典缓存
+export function refreshDict () {
+  return request({
+    url: '/system/dicts/refresh',
+    method: 'get'
+  })
+}
+
+export function pageDict (data) {
+  return request({
+    url: '/system/dicts/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDict (id) {
+  return request({
+    url: '/system/dicts/' + id,
+    method: 'get'
+  })
+}
+
+export function delDict (id) {
+  return request({
+    url: '/system/dicts/' + id,
+    method: 'delete'
+  })
+}
+
+export function delDicts (ids) {
+  return request({
+    url: '/system/dicts/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addDict (data) {
+  return request({
+    url: '/system/dicts',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDict (data) {
+  return request({
+    url: '/system/dicts/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function pageDictItem (data) {
+  return request({
+    url: '/system/dict/items/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDictItem (id) {
+  return request({
+    url: '/system/dict/items/' + id,
+    method: 'get'
+  })
+}
+
+export function delDictItem (id) {
+  return request({
+    url: '/system/dict/items/' + id,
+    method: 'delete'
+  })
+}
+
+export function delDictItems (ids) {
+  return request({
+    url: '/system/dict/items/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addDictItem (data) {
+  return request({
+    url: '/system/dict/items',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDictItem (data) {
+  return request({
+    url: '/system/dict/items/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 54 - 0
src/api/system/menu.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+export function listMenu (data) {
+  return request({
+    url: '/system/menus/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function listMenuForFlow (data) {
+  return request({
+    url: '/system/menus/list/flow',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getMenu (id) {
+  return request({
+    url: '/system/menus/' + id,
+    method: 'get'
+  })
+}
+
+export function delMenu (id) {
+  return request({
+    url: '/system/menus/' + id,
+    method: 'delete'
+  })
+}
+
+export function delMenus (ids) {
+  return request({
+    url: '/system/menus/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addMenu (data) {
+  return request({
+    url: '/system/menus',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateMenu (data) {
+  return request({
+    url: '/system/menus/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 54 - 0
src/api/system/post.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+export function pagePost (data) {
+  return request({
+    url: '/system/posts/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function listPost (data) {
+  return request({
+    url: '/system/posts/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getPost (id) {
+  return request({
+    url: '/system/posts/' + id,
+    method: 'get'
+  })
+}
+
+export function delPost (id) {
+  return request({
+    url: '/system/posts/' + id,
+    method: 'delete'
+  })
+}
+
+export function delPosts (ids) {
+  return request({
+    url: '/system/posts/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addPost (data) {
+  return request({
+    url: '/system/posts',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updatePost (data) {
+  return request({
+    url: '/system/posts/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 54 - 0
src/api/system/role.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+export function pageRole (data) {
+  return request({
+    url: '/system/roles/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function listRole (data) {
+  return request({
+    url: '/system/roles/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getRole (id) {
+  return request({
+    url: '/system/roles/' + id,
+    method: 'get'
+  })
+}
+
+export function delRole (id) {
+  return request({
+    url: '/system/roles/' + id,
+    method: 'delete'
+  })
+}
+
+export function delRoles (ids) {
+  return request({
+    url: '/system/roles/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addRole (data) {
+  return request({
+    url: '/system/roles',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateRole (data) {
+  return request({
+    url: '/system/roles/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 108 - 0
src/api/system/user.js

@@ -0,0 +1,108 @@
+import request from '@/utils/request'
+import qs from 'qs'
+
+export function login(username, password) {
+  const data = {
+    username: username,
+    password: password,
+    grant_type: 'password',
+    scope: 'all'
+  }
+  return request({
+    url: '/auth/oauth/token',
+    method: 'post',
+    headers: {
+      'Authorization': 'Basic ZGF0YXg6MTIzNDU2'
+    },
+    data: qs.stringify(data)
+  })
+}
+
+export function getRoutes() {
+  return request({
+    url: '/system/users/route',
+    method: 'get'
+  })
+}
+
+export function logout(token) {
+  return request({
+    url: `/system/logout/${token}`,
+    method: 'delete'
+  })
+}
+
+export function log() {
+  return request({
+    url: '/system/login/logs',
+    method: 'post'
+  })
+}
+
+export function pageUser(data) {
+  return request({
+    url: '/system/users/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getUser(id) {
+  return request({
+    url: '/system/users/' + id,
+    method: 'get'
+  })
+}
+
+export function delUser(id) {
+  return request({
+    url: '/system/users/' + id,
+    method: 'delete'
+  })
+}
+
+export function delUsers(ids) {
+  return request({
+    url: '/system/users/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addUser(data) {
+  return request({
+    url: '/system/users',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateUser(data) {
+  return request({
+    url: '/system/users/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function updatePassword(data) {
+  return request({
+    url: '/system/users/password',
+    method: 'put',
+    data: data
+  })
+}
+
+export function resetPassword(data) {
+  return request({
+    url: '/system/users/reset/password',
+    method: 'put',
+    data: data
+  })
+}
+
+export function getAuditUsers() {
+  return request({
+    url: '/system/users/audit',
+    method: 'get'
+  })
+}

+ 54 - 0
src/api/visual/databoard.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+export function pageDataBoard(data) {
+  return request({
+    url: '/data/visual/boards/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDataBoard(id) {
+  return request({
+    url: '/data/visual/boards/' + id,
+    method: 'get'
+  })
+}
+
+export function delDataBoard(id) {
+  return request({
+    url: '/data/visual/boards/' + id,
+    method: 'delete'
+  })
+}
+
+export function addDataBoard(data) {
+  return request({
+    url: '/data/visual/boards',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDataBoard(data) {
+  return request({
+    url: '/data/visual/boards/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function copyDataBoard(id) {
+  return request({
+    url: '/data/visual/boards/copy/' + id,
+    method: 'post'
+  })
+}
+
+export function buildDataBoard(data) {
+  return request({
+    url: '/data/visual/boards/build/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 73 - 0
src/api/visual/datachart.js

@@ -0,0 +1,73 @@
+import request from '@/utils/request'
+
+export function listDataChart(data) {
+  return request({
+    url: '/data/visual/charts/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pageDataChart(data) {
+  return request({
+    url: '/data/visual/charts/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDataChart(id) {
+  return request({
+    url: '/data/visual/charts/' + id,
+    method: 'get'
+  })
+}
+
+export function delDataChart(id) {
+  return request({
+    url: '/data/visual/charts/' + id,
+    method: 'delete'
+  })
+}
+
+export function addDataChart(data) {
+  return request({
+    url: '/data/visual/charts',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDataChart(data) {
+  return request({
+    url: '/data/visual/charts/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function copyDataChart(id) {
+  return request({
+    url: '/data/visual/charts/copy/' + id,
+    method: 'post'
+  })
+}
+
+export function buildDataChart(data) {
+  return request({
+    url: '/data/visual/charts/build/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function dataParser(data) {
+  return request({
+    url: '/data/visual/charts/data/parser',
+    headers: {
+      'showLoading': false
+    },
+    method: 'post',
+    data: data
+  })
+}

+ 54 - 0
src/api/visual/datascreen.js

@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+export function pageDataScreen(data) {
+  return request({
+    url: '/data/visual/screens/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDataScreen(id) {
+  return request({
+    url: '/data/visual/screens/' + id,
+    method: 'get'
+  })
+}
+
+export function delDataScreen(id) {
+  return request({
+    url: '/data/visual/screens/' + id,
+    method: 'delete'
+  })
+}
+
+export function addDataScreen(data) {
+  return request({
+    url: '/data/visual/screens',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDataScreen(data) {
+  return request({
+    url: '/data/visual/screens/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function copyDataScreen(id) {
+  return request({
+    url: '/data/visual/screens/copy/' + id,
+    method: 'post'
+  })
+}
+
+export function buildDataScreen(data) {
+  return request({
+    url: '/data/visual/screens/build/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 62 - 0
src/api/visual/dataset.js

@@ -0,0 +1,62 @@
+import request from '@/utils/request'
+
+export function listDataSet(data) {
+  return request({
+    url: '/data/visual/dataSets/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pageDataSet(data) {
+  return request({
+    url: '/data/visual/dataSets/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getDataSet(id) {
+  return request({
+    url: '/data/visual/dataSets/' + id,
+    method: 'get'
+  })
+}
+
+export function delDataSet(id) {
+  return request({
+    url: '/data/visual/dataSets/' + id,
+    method: 'delete'
+  })
+}
+
+export function delDataSets(ids) {
+  return request({
+    url: '/data/visual/dataSets/batch/' + ids,
+    method: 'delete'
+  })
+}
+
+export function addDataSet(data) {
+  return request({
+    url: '/data/visual/dataSets',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateDataSet(data) {
+  return request({
+    url: '/data/visual/dataSets/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function sqlAnalyse(data) {
+  return request({
+    url: '/data/visual/dataSets/sql/analyse',
+    method: 'post',
+    data: data
+  })
+}

+ 46 - 0
src/api/workflow/business.js

@@ -0,0 +1,46 @@
+import request from '@/utils/request'
+
+export function refreshBusiness() {
+  return request({
+    url: '/workflow/business/refresh',
+    method: 'get'
+  })
+}
+
+export function pageBusiness(data) {
+  return request({
+    url: '/workflow/business/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function getBusiness(id) {
+  return request({
+    url: '/workflow/business/' + id,
+    method: 'get'
+  })
+}
+
+export function delBusiness(id) {
+  return request({
+    url: '/workflow/business/' + id,
+    method: 'delete'
+  })
+}
+
+export function addBusiness(data) {
+  return request({
+    url: '/workflow/business',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateBusiness(data) {
+  return request({
+    url: '/workflow/business/' + data.id,
+    method: 'put',
+    data: data
+  })
+}

+ 81 - 0
src/api/workflow/definition.js

@@ -0,0 +1,81 @@
+import request from '@/utils/request'
+
+export function listCategory(data) {
+  return request({
+    url: '/workflow/categorys/list',
+    method: 'get',
+    params: data
+  })
+}
+
+export function addCategory(data) {
+  return request({
+    url: '/workflow/categorys',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateCategory(data) {
+  return request({
+    url: '/workflow/categorys/' + data.id,
+    method: 'put',
+    data: data
+  })
+}
+
+export function delCategory(id) {
+  return request({
+    url: '/workflow/categorys/' + id,
+    method: 'delete'
+  })
+}
+
+export function pageDefinition(data) {
+  return request({
+    url: '/workflow/definitions/page',
+    method: 'get',
+    params: data
+  })
+}
+
+export function delDefinition(deploymentId) {
+  return request({
+    url: '/workflow/definitions/delete/' + deploymentId,
+    method: 'delete'
+  })
+}
+
+export function activateDefinition(processDefinitionId) {
+  return request({
+    url: '/workflow/definitions/activate/' + processDefinitionId,
+    method: 'put'
+  })
+}
+
+export function suspendDefinition(processDefinitionId) {
+  return request({
+    url: '/workflow/definitions/suspend/' + processDefinitionId,
+    method: 'put'
+  })
+}
+
+export function deployDefinition(data) {
+  return request({
+    url: '/workflow/definitions/import/file',
+    method: 'post',
+    headers: {
+      'Content-Type': 'multipart/form-data'
+    },
+    data: data
+  })
+}
+
+export function flowResource(processDefinitionId) {
+  return request({
+    url: '/workflow/definitions/resource',
+    method: 'get',
+    responseType: 'blob',
+    params: { processDefinitionId: processDefinitionId, resType: 'image' }
+  })
+}

+ 55 - 0
src/api/workflow/instance.js

@@ -0,0 +1,55 @@
+import request from '@/utils/request'
+
+export function pageRunningInstance(data) {
+  return request({
+    url: '/workflow/instances/pageRunning',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pageMyStartedInstance(data) {
+  return request({
+    url: '/workflow/instances/pageMyStarted',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pageMyInvolvedInstance(data) {
+  return request({
+    url: '/workflow/instances/pageMyInvolved',
+    method: 'get',
+    params: data
+  })
+}
+
+export function delInstance(processInstanceId) {
+  return request({
+    url: '/workflow/instances/delete/' + processInstanceId,
+    method: 'delete'
+  })
+}
+
+export function activateInstance(processInstanceId) {
+  return request({
+    url: '/workflow/instances/activate/' + processInstanceId,
+    method: 'put'
+  })
+}
+
+export function suspendInstance(processInstanceId) {
+  return request({
+    url: '/workflow/instances/suspend/' + processInstanceId,
+    method: 'put'
+  })
+}
+
+export function flowTrack(processInstanceId) {
+  return request({
+    url: '/workflow/instances/track',
+    method: 'get',
+    responseType: 'blob',
+    params: { processInstanceId: processInstanceId }
+  })
+}

+ 25 - 0
src/api/workflow/task.js

@@ -0,0 +1,25 @@
+import request from '@/utils/request'
+
+export function pageTodoTask(data) {
+  return request({
+    url: '/workflow/tasks/pageTodo',
+    method: 'get',
+    params: data
+  })
+}
+
+export function pageDoneTask(data) {
+  return request({
+    url: '/workflow/tasks/pageDone',
+    method: 'get',
+    params: data
+  })
+}
+
+export function executeTask(data) {
+  return request({
+    url: '/workflow/tasks/execute/' + data.taskId,
+    method: 'post',
+    data: data
+  })
+}

BIN
src/assets/401_images/401.gif


BIN
src/assets/404_images/404.png


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


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 3 - 0
src/assets/icons/iconfont.css


BIN
src/assets/icons/iconfont.eot


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
src/assets/icons/iconfont.js


+ 471 - 0
src/assets/icons/iconfont.json

@@ -0,0 +1,471 @@
+{
+  "id": "1608019",
+  "name": "datax-ui",
+  "font_family": "iconfont",
+  "css_prefix_text": "icon-",
+  "description": "",
+  "glyphs": [
+    {
+      "icon_id": "3862606",
+      "name": "极坐标图",
+      "font_class": "chart_polar_active",
+      "unicode": "e618",
+      "unicode_decimal": 58904
+    },
+    {
+      "icon_id": "12450533",
+      "name": "树图",
+      "font_class": "chart_tree_active",
+      "unicode": "e94d",
+      "unicode_decimal": 59725
+    },
+    {
+      "icon_id": "18082708",
+      "name": "树图",
+      "font_class": "chart_tree",
+      "unicode": "e94f",
+      "unicode_decimal": 59727
+    },
+    {
+      "icon_id": "18082601",
+      "name": "极坐标图",
+      "font_class": "chart_polar",
+      "unicode": "e94e",
+      "unicode_decimal": 59726
+    },
+    {
+      "icon_id": "6791681",
+      "name": "fsux_图表_表格",
+      "font_class": "chart_table",
+      "unicode": "e601",
+      "unicode_decimal": 58881
+    },
+    {
+      "icon_id": "7009346",
+      "name": "水球图",
+      "font_class": "chart_liquidfill_active",
+      "unicode": "e65f",
+      "unicode_decimal": 58975
+    },
+    {
+      "icon_id": "12746969",
+      "name": "fsux_图表_表格",
+      "font_class": "chart_table_active",
+      "unicode": "e616",
+      "unicode_decimal": 58902
+    },
+    {
+      "icon_id": "17078539",
+      "name": "水球图",
+      "font_class": "chart_liquidfill",
+      "unicode": "e602",
+      "unicode_decimal": 58882
+    },
+    {
+      "icon_id": "4781595",
+      "name": "旭日图",
+      "font_class": "chart_sunburst",
+      "unicode": "e60e",
+      "unicode_decimal": 58894
+    },
+    {
+      "icon_id": "4781609",
+      "name": "漏斗图",
+      "font_class": "chart_funnel",
+      "unicode": "e614",
+      "unicode_decimal": 58900
+    },
+    {
+      "icon_id": "4781612",
+      "name": "桑基图",
+      "font_class": "chart_sankey",
+      "unicode": "e615",
+      "unicode_decimal": 58901
+    },
+    {
+      "icon_id": "4781685",
+      "name": "指标卡",
+      "font_class": "chart_kpi",
+      "unicode": "e617",
+      "unicode_decimal": 58903
+    },
+    {
+      "icon_id": "4878750",
+      "name": "漏斗图",
+      "font_class": "chart_funnel_active",
+      "unicode": "e62a",
+      "unicode_decimal": 58922
+    },
+    {
+      "icon_id": "4878756",
+      "name": "桑基图",
+      "font_class": "chart_sankey_active",
+      "unicode": "e634",
+      "unicode_decimal": 58932
+    },
+    {
+      "icon_id": "4878762",
+      "name": "旭日图",
+      "font_class": "chart_sunburst_active",
+      "unicode": "e635",
+      "unicode_decimal": 58933
+    },
+    {
+      "icon_id": "4879224",
+      "name": "指标卡",
+      "font_class": "chart_kpi_active",
+      "unicode": "e636",
+      "unicode_decimal": 58934
+    },
+    {
+      "icon_id": "10451644",
+      "name": "环形图",
+      "font_class": "chart_donut_active",
+      "unicode": "e622",
+      "unicode_decimal": 58914
+    },
+    {
+      "icon_id": "10451648",
+      "name": "雷达图",
+      "font_class": "chart_radar_active",
+      "unicode": "e623",
+      "unicode_decimal": 58915
+    },
+    {
+      "icon_id": "10451655",
+      "name": "矩形树图",
+      "font_class": "chart_treemap_active",
+      "unicode": "e624",
+      "unicode_decimal": 58916
+    },
+    {
+      "icon_id": "10451656",
+      "name": "散点图",
+      "font_class": "chart_scatter_active",
+      "unicode": "e625",
+      "unicode_decimal": 58917
+    },
+    {
+      "icon_id": "10451658",
+      "name": "仪表盘",
+      "font_class": "chart_gauge_active",
+      "unicode": "e626",
+      "unicode_decimal": 58918
+    },
+    {
+      "icon_id": "10451663",
+      "name": "基本柱状图",
+      "font_class": "chart_bar_active",
+      "unicode": "e628",
+      "unicode_decimal": 58920
+    },
+    {
+      "icon_id": "10451666",
+      "name": "基本折线图",
+      "font_class": "chart_line_active",
+      "unicode": "e629",
+      "unicode_decimal": 58921
+    },
+    {
+      "icon_id": "10451680",
+      "name": "基本折线图",
+      "font_class": "chart_line",
+      "unicode": "e62b",
+      "unicode_decimal": 58923
+    },
+    {
+      "icon_id": "10451684",
+      "name": "环形图",
+      "font_class": "chart_donut",
+      "unicode": "e62c",
+      "unicode_decimal": 58924
+    },
+    {
+      "icon_id": "10451687",
+      "name": "基本柱状图",
+      "font_class": "chart_bar",
+      "unicode": "e62e",
+      "unicode_decimal": 58926
+    },
+    {
+      "icon_id": "10451690",
+      "name": "散点图",
+      "font_class": "chart_scatter",
+      "unicode": "e630",
+      "unicode_decimal": 58928
+    },
+    {
+      "icon_id": "10451695",
+      "name": "矩形树图",
+      "font_class": "chart_treemap",
+      "unicode": "e631",
+      "unicode_decimal": 58929
+    },
+    {
+      "icon_id": "10451701",
+      "name": "雷达图",
+      "font_class": "chart_radar",
+      "unicode": "e632",
+      "unicode_decimal": 58930
+    },
+    {
+      "icon_id": "10451703",
+      "name": "仪表盘",
+      "font_class": "chart_gauge",
+      "unicode": "e633",
+      "unicode_decimal": 58931
+    },
+    {
+      "icon_id": "11671969",
+      "name": "词云",
+      "font_class": "chart_wordcloud_active",
+      "unicode": "e66f",
+      "unicode_decimal": 58991
+    },
+    {
+      "icon_id": "11671976",
+      "name": "地图",
+      "font_class": "chart_geo_active",
+      "unicode": "e670",
+      "unicode_decimal": 58992
+    },
+    {
+      "icon_id": "11671984",
+      "name": "词云",
+      "font_class": "chart_wordcloud",
+      "unicode": "e672",
+      "unicode_decimal": 58994
+    },
+    {
+      "icon_id": "11671987",
+      "name": "地图",
+      "font_class": "chart_geo",
+      "unicode": "e673",
+      "unicode_decimal": 58995
+    },
+    {
+      "icon_id": "10451635",
+      "name": "饼图",
+      "font_class": "chart_pie_active",
+      "unicode": "e63b",
+      "unicode_decimal": 58939
+    },
+    {
+      "icon_id": "10451672",
+      "name": "饼图",
+      "font_class": "chart_pie",
+      "unicode": "e650",
+      "unicode_decimal": 58960
+    },
+    {
+      "icon_id": "12150272",
+      "name": "文件夹",
+      "font_class": "-folder-empty3",
+      "unicode": "e64f",
+      "unicode_decimal": 58959
+    },
+    {
+      "icon_id": "10798549",
+      "name": "组织",
+      "font_class": "zuzhi",
+      "unicode": "e67d",
+      "unicode_decimal": 59005
+    },
+    {
+      "icon_id": "4186384",
+      "name": "数据字段",
+      "font_class": "shujuziduan",
+      "unicode": "e658",
+      "unicode_decimal": 58968
+    },
+    {
+      "icon_id": "4305953",
+      "name": "数据表",
+      "font_class": "shujubiao",
+      "unicode": "e686",
+      "unicode_decimal": 59014
+    },
+    {
+      "icon_id": "7159343",
+      "name": "数据库",
+      "font_class": "shujuku",
+      "unicode": "e64e",
+      "unicode_decimal": 58958
+    },
+    {
+      "icon_id": "9720183",
+      "name": "维度",
+      "font_class": "weidu",
+      "unicode": "e64c",
+      "unicode_decimal": 58956
+    },
+    {
+      "icon_id": "15381567",
+      "name": "指标",
+      "font_class": "zhibiao",
+      "unicode": "e64d",
+      "unicode_decimal": 58957
+    },
+    {
+      "icon_id": "8841995",
+      "name": "刷新",
+      "font_class": "shuaxin",
+      "unicode": "e63f",
+      "unicode_decimal": 58943
+    },
+    {
+      "icon_id": "7817227",
+      "name": "设置",
+      "font_class": "shezhi",
+      "unicode": "e613",
+      "unicode_decimal": 58899
+    },
+    {
+      "icon_id": "4767026",
+      "name": "colum-height",
+      "font_class": "colum-height",
+      "unicode": "e7ef",
+      "unicode_decimal": 59375
+    },
+    {
+      "icon_id": "4767092",
+      "name": "column-width",
+      "font_class": "column-width",
+      "unicode": "e7fc",
+      "unicode_decimal": 59388
+    },
+    {
+      "icon_id": "9519626",
+      "name": "ScreenFull",
+      "font_class": "ScreenFull",
+      "unicode": "e83a",
+      "unicode_decimal": 59450
+    },
+    {
+      "icon_id": "6664146",
+      "name": "dashboard",
+      "font_class": "dashboard",
+      "unicode": "e60b",
+      "unicode_decimal": 58891
+    },
+    {
+      "icon_id": "287169",
+      "name": "删除",
+      "font_class": "shanchu",
+      "unicode": "e62d",
+      "unicode_decimal": 58925
+    },
+    {
+      "icon_id": "427205",
+      "name": "新增",
+      "font_class": "xinzeng",
+      "unicode": "e64a",
+      "unicode_decimal": 58954
+    },
+    {
+      "icon_id": "584245",
+      "name": "搜索",
+      "font_class": "sousuo",
+      "unicode": "e62f",
+      "unicode_decimal": 58927
+    },
+    {
+      "icon_id": "1013824",
+      "name": "PDF文件",
+      "font_class": "pdf",
+      "unicode": "e78d",
+      "unicode_decimal": 59277
+    },
+    {
+      "icon_id": "1069107",
+      "name": "修改",
+      "font_class": "xiugai",
+      "unicode": "e63a",
+      "unicode_decimal": 58938
+    },
+    {
+      "icon_id": "3978297",
+      "name": "退出",
+      "font_class": "tuichu",
+      "unicode": "e641",
+      "unicode_decimal": 58945
+    },
+    {
+      "icon_id": "4360962",
+      "name": "查看",
+      "font_class": "chakan",
+      "unicode": "e600",
+      "unicode_decimal": 58880
+    },
+    {
+      "icon_id": "4889788",
+      "name": "头像",
+      "font_class": "touxiang",
+      "unicode": "e620",
+      "unicode_decimal": 58912
+    },
+    {
+      "icon_id": "5321591",
+      "name": "Excel",
+      "font_class": "excel",
+      "unicode": "e637",
+      "unicode_decimal": 58935
+    },
+    {
+      "icon_id": "5653009",
+      "name": "重置密码",
+      "font_class": "psw-reset",
+      "unicode": "e7de",
+      "unicode_decimal": 59358
+    },
+    {
+      "icon_id": "5666416",
+      "name": "下载",
+      "font_class": "xiazai",
+      "unicode": "e611",
+      "unicode_decimal": 58897
+    },
+    {
+      "icon_id": "5666420",
+      "name": "上传",
+      "font_class": "shangchuan",
+      "unicode": "e612",
+      "unicode_decimal": 58898
+    },
+    {
+      "icon_id": "6265237",
+      "name": "菜单",
+      "font_class": "menu-line",
+      "unicode": "e653",
+      "unicode_decimal": 58963
+    },
+    {
+      "icon_id": "6326748",
+      "name": "重置",
+      "font_class": "chongzhi",
+      "unicode": "e627",
+      "unicode_decimal": 58919
+    },
+    {
+      "icon_id": "8765263",
+      "name": "word",
+      "font_class": "word",
+      "unicode": "e640",
+      "unicode_decimal": 58944
+    },
+    {
+      "icon_id": "9512645",
+      "name": "提交",
+      "font_class": "submit",
+      "unicode": "e638",
+      "unicode_decimal": 58936
+    },
+    {
+      "icon_id": "10166354",
+      "name": "size",
+      "font_class": "size",
+      "unicode": "e63c",
+      "unicode_decimal": 58940
+    }
+  ]
+}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 22 - 0
src/assets/icons/iconfont.svg


BIN
src/assets/icons/iconfont.ttf


BIN
src/assets/icons/iconfont.woff


BIN
src/assets/icons/iconfont.woff2


BIN
src/assets/images/login-bg.jpg


+ 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="index === 0">当前位置:</span>
+        <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)
+    },
+    isDashboard(route) {
+      const name = route && route.name
+      if (!name) {
+        return false
+      }
+      return name.trim().toLocaleLowerCase() === '首页'.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>

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

@@ -0,0 +1,44 @@
+<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" />
+    </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;
+}
+
+.hamburger.is-active {
+  transform: rotate(180deg);
+}
+</style>

+ 544 - 0
src/components/PivotTable/index.vue

@@ -0,0 +1,544 @@
+<template>
+  <div class="table-responsive">
+    <table>
+      <!-- Table header -->
+      <thead>
+        <tr v-for="(tr, index) in combineHeads" :key="index">
+          <th v-for="cell in tr" :key="cell.__index" :rowspan="cell.rowspan" :colspan="cell.colspan">
+            <div :class="{ 'col-corner-bg': cell.isCorner }" :style="{ 'min-height': _getMinHeightByRowCount(cell.rowspan) }">
+              {{ cell.isCorner ? (rowPaths.length + ' x ' + colPaths.length) : cell.value }}
+            </div>
+          </th>
+        </tr>
+      </thead>
+      <!-- Table body -->
+      <tbody>
+        <tr v-for="(tr, index) in combineValues" :key="index">
+          <!-- Row headers -->
+          <th v-for="cell in tr.head" v-if="!cell.isRowspan" :key="cell.__index" :rowspan="cell.rowspan" :colspan="cell.colspan">
+            <div :style="{ 'min-height': _getMinHeightByRowCount(cell.rowspan) }">
+              {{ cell.value }}
+            </div>
+          </th>
+          <!-- Values -->
+          <td v-for="cell in tr.data" :key="cell.__index" :rowspan="cell.rowspan" :colspan="cell.colspan">
+            <div :style="{ 'min-height': _getMinHeightByRowCount(cell.rowspan) }">
+              {{ cell.value }}
+            </div>
+          </td>
+        </tr>
+      </tbody>
+    </table>
+  </div>
+</template>
+
+<script>
+import { mergeBaseInfo, convertPathToMap, getHeightByCount, SEPARATOR } from '@/utils/visual-chart'
+
+export default {
+  name: 'PivotTable',
+  props: {
+    data: {
+      type: Array,
+      default: () => []
+    },
+    rows: {
+      type: Array,
+      default: () => []
+    },
+    columns: {
+      type: Array,
+      default: () => []
+    },
+    values: {
+      type: Array,
+      default: () => []
+    }
+  },
+  data: () => ({
+    localRows: [],
+    localColumns: [],
+    localValues: [],
+    localData: [],
+    // 计算列的数据
+    calcData: [],
+    // Separator
+    Separator: SEPARATOR,
+    // 合并后的表头
+    combineHeads: [],
+    // 合并后的单元格
+    combineValues: []
+  }),
+  computed: {
+    watchAllProps() {
+      const { rows, columns, values, data } = this
+      return { rows, columns, values, data }
+    },
+    rowPaths() {
+      const _paths = this._combineRowPaths(
+        this.localData,
+        ...this.localRows.map(({ key, values }) => { return { key, values } })
+      )
+      return _paths
+    },
+    colPaths() {
+      const keys = this.localColumns.map(({ values }) => values)
+      if (this.localValues.length) {
+        keys.push(this.localValues.map(({ key }) => key))
+      }
+      const _paths = this._combineColPaths(...keys)
+      return _paths
+    },
+    // 列的表头
+    colHeads() {
+      // 共有多少行
+      const _rows = this.localColumns.map(() => [])
+      // 有几个值
+      const valuesLen = this.localValues.length
+      if (valuesLen) {
+        _rows.push([])
+      }
+      // 计算合并单元格
+      const colSpans = {}
+      this.colPaths.forEach((path, pathIndex) => {
+        // 条件值
+        const pathValues = path.split(this.Separator)
+        // 存储路径
+        const currPath = []
+        _rows.forEach((row, rowIndex) => {
+          const cellData = {}
+          const currVal = pathValues[rowIndex] || ''
+          // 是否为 values 行
+          const isLastRow = rowIndex === _rows.length - 1
+          // 存储路径
+          currPath.push(currVal)
+          const baseX = rowIndex
+          const baseY = this.localRows.length + pathIndex
+          if (!isLastRow) {
+            // 计算合并行数
+            let compareVal = valuesLen
+            for (let i = rowIndex; i < this.localColumns.length - 1; i++) {
+              compareVal *= this.localColumns[rowIndex + 1].values.length
+            }
+            const currColSpan = colSpans[rowIndex] || {}
+            const currColSpanVal = (currColSpan[currPath.join(this.Separator)] || 0) + 1
+            currColSpan[currPath.join(this.Separator)] = currColSpanVal
+            colSpans[rowIndex] = currColSpan
+            // 合并单元格:起始单元格加入
+            if (currColSpanVal === 1) {
+              row.push(
+                Object.assign(
+                  cellData,
+                  mergeBaseInfo({
+                    __index: `${baseX}-${baseY}`,
+                    x: baseX,
+                    y: baseY,
+                    colspan: compareVal,
+                    path: currPath.filter((item) => !!item),
+                    value: currVal
+                  })
+                )
+              )
+            }
+          } else {
+            row.push(
+              Object.assign(
+                cellData,
+                mergeBaseInfo({
+                  __index: `${baseX}-${baseY}`,
+                  x: baseX,
+                  y: baseY,
+                  path: currPath.filter((item) => !!item),
+                  // 最后一行是 values,替换显示文本
+                  value: this.localValues.find(({ key }) => key === currVal).label
+                })
+              )
+            )
+          }
+        })
+      })
+      return _rows
+    },
+    // 行的表头
+    rowHeads() {
+      // 共有多少列
+      const _columns = []
+      // 左上角特殊处理, 有行维、列维时才有
+      const columnsLen = this.localColumns.length
+      const rowsLen = this.localRows.length
+      if (rowsLen && columnsLen) {
+        _columns.push(mergeBaseInfo({
+          __index: `0-0`,
+          colspan: this.localRows.length,
+          rowspan: this.localColumns.length,
+          // 左上角标记
+          isCorner: true
+        }))
+      }
+      this.localRows.forEach(({ label }, index) => {
+        _columns.push(mergeBaseInfo({
+          __index: `${this.localColumns.length}-${index}`,
+          value: label,
+          x: this.localColumns.length,
+          y: index
+        }))
+      })
+      return _columns
+    },
+    // 行对应的值
+    rowHeadValues() {
+      let _values = []
+      const rowsLen = this.localRows.length
+      if (rowsLen) {
+        // 计算合并单元格
+        const rowSpans = {}
+        _values = this.rowPaths.map((path, pathIndex) => {
+          const values = path.split(this.Separator)
+          const currPath = []
+          return this.localRows.map((item, rowIndex) => {
+            const currVal = values[rowIndex] || ''
+            const baseX = this.localColumns.length + +Boolean(this.localValues.length) + pathIndex
+            const baseY = rowIndex
+            currPath.push(currVal)
+            // 是否为最后列
+            const isLastCol = rowIndex === rowsLen - 1
+            if (!isLastCol) {
+              // 计算合并列数
+              // 过滤条件
+              const conditions = {}
+              for (let i = 0; i < rowIndex + 1; i++) {
+                conditions[i] = values[i] || ''
+              }
+              const filterData = this.rowPaths.filter((data) => {
+                let status = true
+                const splitValues = data.split(this.Separator)
+                for (const key in conditions) {
+                  if (conditions[key] !== splitValues[key]) {
+                    status = false
+                    return
+                  }
+                }
+                return status
+              }) || []
+              const mergeSpans = filterData.length
+              const currRowSpan = rowSpans[rowIndex] || {}
+              const currRowSpanVal = (currRowSpan[currPath.join(this.Separator)] || 0) + 1
+              currRowSpan[currPath.join(this.Separator)] = currRowSpanVal
+              rowSpans[rowIndex] = currRowSpan
+              if (currRowSpanVal === 1) {
+                return mergeBaseInfo({
+                  __index: `${baseX}-${baseY}`,
+                  value: currVal,
+                  x: baseX,
+                  y: baseY,
+                  rowspan: mergeSpans,
+                  path: currPath.filter((item) => !!item)
+                })
+              } else {
+                return mergeBaseInfo({
+                  __index: `${baseX}-${baseY}`,
+                  value: currVal,
+                  x: baseX,
+                  y: baseY,
+                  path: currPath.filter((item) => !!item),
+                  // 是否合并单元格,遍历时判断不显示
+                  isRowspan: true
+                })
+              }
+            } else {
+              return mergeBaseInfo({
+                __index: `${baseX}-${baseY}`,
+                value: currVal,
+                x: baseX,
+                y: baseY,
+                path: currPath.filter((item) => !!item)
+              })
+            }
+          })
+        })
+      }
+      return _values
+    },
+    // 计算所有对应条件的值
+    dataValues() {
+      // 列对应的条件
+      const colConditions = convertPathToMap(
+        this.colPaths,
+        this.localColumns.map(({ key }) => key).concat(this.localValues.length ? ['value'] : [])
+      )
+      // 行对应的条件
+      const rowConditions = convertPathToMap(
+        this.rowPaths,
+        this.localRows.map(({ key }) => key)
+      )
+      // console.log('colConditions', colConditions)
+      // console.log('rowConditions', rowConditions)
+      // 针对没传入行或列的处理
+      !colConditions.length && colConditions.push({})
+      !rowConditions.length && rowConditions.push({})
+      // 过滤数据, 遍历行以及遍历行对应的列
+      return rowConditions.map((rowCondition, rowConditionIndex) => {
+        const _data = colConditions.map((colCondition, colConditionIndex) => {
+          // 存储当前单元对应的数据
+          const cellData = {}
+          // 当前单元对应的条件
+          const conditions = Object.assign({}, rowCondition, colCondition)
+          const _filterConditions = Object.fromEntries(
+            Object.entries(conditions).filter(
+              (item) => item[0] !== 'value'
+            )
+          )
+          // 通过当前单元对应的条件,过滤数据
+          const filterData = this._filterData(_filterConditions, this.localData)
+          // 对应表格的坐标位置
+          const baseX = this.localColumns.length + +Boolean(this.localValues.length) + rowConditionIndex
+          const baseY = this.localRows.length + colConditionIndex
+          Object.assign(
+            cellData,
+            mergeBaseInfo({
+              conditions,
+              x: baseX,
+              y: baseY,
+              __index: `${baseX}-${baseY}`
+            })
+          )
+          // 针对为指定值 props.values 的空处理(绘制空表格)
+          const isEmptyValues = this.localColumns.length && this.localRows.length && !this.localValues.length
+          if (isEmptyValues) {
+            Object.assign(cellData, { value: '' })
+          } else {
+            // 从 props.values 中找出对应的值
+            const _value = this.values.find(({ key }) => key === conditions.value)
+            Object.assign(cellData, { value: _value && _value.key ? this._reduceValue(filterData, _value.key) : '' })
+          }
+          return cellData
+        })
+        return {
+          __index: _data[0].x,
+          data: _data
+        }
+      })
+    }
+  },
+  watch: {
+    watchAllProps() {
+      this.init()
+    }
+  },
+  created() {
+    this.init()
+  },
+  methods: {
+    init() {
+      if (this.rows.length || this.columns.length || this.values.length) {
+        this.handleDataClone()
+        this.setValuesToColAndRow()
+        this.handleCalcData()
+        this.handleCombineHeads()
+        this.handleCombineValues()
+      } else {
+        console.warn('[Warn]: props.rows, props.columns, props.values at least one is not empty.')
+      }
+    },
+    // clone data
+    handleDataClone() {
+      this.localRows = JSON.parse(JSON.stringify(this.rows))
+      this.localColumns = JSON.parse(JSON.stringify(this.columns))
+      this.localValues = JSON.parse(JSON.stringify(this.values))
+      this.localData = Object.freeze(this.data)
+    },
+    // set the `values` attribute to rows and columns
+    setValuesToColAndRow() {
+      const rowKeys = this.localRows.map(({ key }) => key)
+      const columnKeys = this.localColumns.map(({ key }) => key)
+      const rowValues = this._findCategory(rowKeys, this.localData)
+      const columnValues = this._findCategory(columnKeys, this.localData)
+      this.localRows.forEach((row) => {
+        const { key, values } = row
+        this.$set(row, 'values', values || rowValues[key] || [])
+      })
+      this.localColumns.forEach((column) => {
+        const { key, values } = column
+        this.$set(column, 'values', values || columnValues[key] || [])
+      })
+    },
+    // 合并表头
+    handleCombineHeads() {
+      let combineColHeads = JSON.parse(JSON.stringify(this.colHeads))
+      combineColHeads[0] = combineColHeads[0] || []
+      combineColHeads[0].unshift(...this.rowHeads.filter((item) => item.isCorner))
+      combineColHeads[combineColHeads.length - 1].unshift(...this.rowHeads.filter((item) => !item.isCorner))
+      combineColHeads = combineColHeads.filter((item) => item.length)
+      this.combineHeads = combineColHeads
+    },
+    // 合并值
+    handleCombineValues() {
+      // values
+      const combineValues = []
+      const valueRowCount = this.dataValues.length || this.rowHeadValues.length
+      for (let i = 0; i < valueRowCount; i++) {
+        const _currRowHeadValue = this.rowHeadValues[i] || []
+        const _currValue = this.dataValues[i] || {}
+        const _row = [...(_currValue.data || [])]
+        combineValues.push(
+          Object.assign({}, { head: [..._currRowHeadValue] }, { data: _row })
+        )
+      }
+      this.combineValues = combineValues
+    },
+    // 初始计算值
+    handleCalcData() {
+      if (!this.localValues.length) return
+      const _rowPaths = this._combineRowPaths(
+        this.localData,
+        ...this.localRows.map(({ key, values }) => { return { key, values } })
+      )
+      const _rowKeys = this.localRows.map(({ key }) => key)
+      const _colPaths = this._combineColPaths(
+        ...this.localColumns.map(({ values }) => values)
+      )
+      const _colKeys = this.localColumns.map(({ key }) => key)
+      // conditions of col-head
+      const colConditions = convertPathToMap(_colPaths, _colKeys)
+      // conditions of row-head
+      const rowConditions = convertPathToMap(_rowPaths, _rowKeys)
+      // Note: if there are no props.rows or props.columns, push an empty object
+      !colConditions.length && colConditions.push({})
+      !rowConditions.length && rowConditions.push({})
+      // draw data
+      this.calcData = Object.freeze(
+        rowConditions
+          .map((rowCondition, rowConditionIndex) =>
+            colConditions
+              .map((colCondition, colConditionIndex) => {
+                // the condition of current cell
+                const conditions = Object.assign({}, rowCondition, colCondition)
+                // filter the data
+                const filterData = this._filterData(conditions, this.localData)
+                // empty cell
+                const isEmptyCell = this.localRows.length && this.localColumns.length && !this.localValues.length
+                const _values = {}
+                // 多个值,多条数据
+                this.values.forEach(({ key }) => {
+                  _values[key] = isEmptyCell ? '' : this._reduceValue(filterData, key)
+                })
+                return Object.assign({}, conditions, _values)
+              })
+              .flat()
+          )
+          .filter((item) => item.length)
+          .flat()
+      )
+    },
+    _combineRowPaths(data, ...arrays) {
+      const len = arrays.length
+      let _result = []
+      if (len) {
+        const rowPaths = arrays.reduce((prev, curr) => {
+          const arr = []
+          prev.values.forEach(_prevEl => {
+            const prevKey = prev.key.split(SEPARATOR)
+            curr.values.forEach(_currEl => {
+              const currKey = curr.key
+              const conditions = {}
+              prevKey.forEach((key, i) => {
+                conditions[key] = _prevEl.split(SEPARATOR)[i]
+              })
+              conditions[currKey] = _currEl
+              // 判断数据里是否有该项
+              const filter = data.some((data) => {
+                let status = true
+                for (const key in conditions) {
+                  if (conditions[key] !== data[key]) {
+                    status = false
+                    return
+                  }
+                }
+                return status
+              })
+              if (filter) {
+                arr.push(_prevEl + SEPARATOR + _currEl)
+              }
+            })
+          })
+          return { key: prev.key + SEPARATOR + curr.key, values: arr }
+        }) || {}
+        _result = rowPaths.values || []
+      }
+      return _result
+    },
+    _combineColPaths(...arrays) {
+      return arrays.length ? arrays.reduce((prev, curr) => {
+        const arr = []
+        prev.forEach(_prevEl => {
+          curr.forEach(_currEl => {
+            arr.push(_prevEl + SEPARATOR + _currEl)
+          })
+        })
+        return arr
+      }) : arrays
+    },
+    _findCategory(keys = [], data = []) {
+      const _result = {}
+      data.forEach(item => {
+        keys.forEach(key => {
+          // Remove duplicates
+          _result[key] = _result[key] || []
+          _result[key].push(item[key])
+          _result[key] = [...new Set(_result[key])]
+        })
+      })
+      return _result
+    },
+    _reduceValue(data, key) {
+      if (!data.length) return ''
+      return data.reduce((sum, item) => { return sum + Number(item[key]) }, 0)
+    },
+    _filterData(conditions, data) {
+      return data.filter((data) => {
+        let status = true
+        for (const key in conditions) {
+          if (conditions[key] !== data[key]) {
+            status = false
+            return
+          }
+        }
+        return status
+      })
+    },
+    // get min height by rowspan
+    _getMinHeightByRowCount(count) {
+      return getHeightByCount(count)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+table {
+  border-collapse: collapse;
+  border-spacing: 0;
+  border: none;
+  td, th {
+    border: 1px solid #ccc;
+    padding: 0;
+    vertical-align: middle;
+    box-sizing: border-box;
+    > div {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      box-sizing: border-box;
+      padding: 5px;
+      text-align: center;
+      white-space: nowrap;
+      width: 100%;
+      height: 100%;
+      min-height: 36px;
+      cursor: default;
+      &.col-corner-bg {
+      }
+    }
+  }
+}
+</style>

+ 60 - 0
src/components/Screenfull/index.vue

@@ -0,0 +1,60 @@
+<template>
+  <div>
+    <svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" />
+  </div>
+</template>
+
+<script>
+import screenfull from 'screenfull'
+
+export default {
+  name: 'Screenfull',
+  data() {
+    return {
+      isFullscreen: false
+    }
+  },
+  mounted() {
+    this.init()
+  },
+  beforeDestroy() {
+    this.destroy()
+  },
+  methods: {
+    click() {
+      if (!screenfull.isEnabled) {
+        this.$message({
+          message: 'you browser can not work',
+          type: 'warning'
+        })
+        return false
+      }
+      screenfull.toggle()
+    },
+    change() {
+      this.isFullscreen = screenfull.isFullscreen
+    },
+    init() {
+      if (screenfull.isEnabled) {
+        screenfull.on('change', this.change)
+      }
+    },
+    destroy() {
+      if (screenfull.isEnabled) {
+        screenfull.off('change', this.change)
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.screenfull-svg {
+  display: inline-block;
+  cursor: pointer;
+  fill: #5a5e66;;
+  width: 20px;
+  height: 20px;
+  vertical-align: 10px;
+}
+</style>

+ 110 - 0
src/components/SqlEditor/index.vue

@@ -0,0 +1,110 @@
+<template>
+  <div>
+    <textarea
+      ref="mycode"
+      v-model="value"
+      class="codesql"
+    />
+  </div>
+</template>
+
+<script>
+import 'codemirror/lib/codemirror.css'
+import 'codemirror/theme/blackboard.css'
+import 'codemirror/addon/hint/show-hint.css'
+const CodeMirror = require('codemirror/lib/codemirror')
+require('codemirror/addon/edit/matchbrackets')
+require('codemirror/addon/selection/active-line')
+require('codemirror/mode/sql/sql')
+require('codemirror/addon/hint/show-hint')
+require('codemirror/addon/hint/sql-hint')
+
+export default {
+  name: 'SqlEditor',
+  props: {
+    value: {
+      type: String,
+      default: ''
+    },
+    sqlStyle: {
+      type: String,
+      default: 'default'
+    },
+    readOnly: {
+      type: [Boolean, String]
+    }
+  },
+  data() {
+    return {
+      editor: null
+    }
+  },
+  computed: {
+    newVal() {
+      if (this.editor) {
+        return this.editor.getValue()
+      }
+    }
+  },
+  watch: {
+    newVal(newV, oldV) {
+      if (this.editor) {
+        this.$emit('changeTextarea', this.editor.getValue())
+      }
+    }
+  },
+  mounted() {
+    const mime = 'text/x-mariadb'
+    const theme = 'blackboard'// 设置主题,不设置的会使用默认主题
+    this.editor = CodeMirror.fromTextArea(this.$refs.mycode, {
+      value: this.value,
+      mode: mime, // 选择对应代码编辑器的语言,我这边选的是数据库,根据个人情况自行设置即可
+      indentWithTabs: true,
+      smartIndent: true,
+      lineNumbers: true,
+      matchBrackets: true,
+      cursorHeight: 1,
+      lineWrapping: true,
+      readOnly: this.readOnly,
+      theme: theme,
+      autofocus: true,
+      extraKeys: { 'Ctrl': 'autocomplete' }, // 自定义快捷键
+      hintOptions: { // 自定义提示选项
+        // 当匹配只有一项的时候是否自动补全
+        completeSingle: false
+        // tables: {
+        //     users: ['name', 'score', 'birthDate'],
+        //     countries: ['name', 'population', 'size']
+        // }
+      }
+    })
+    // 代码自动提示功能,记住使用cursorActivity事件不要使用change事件,这是一个坑,那样页面直接会卡死
+    this.editor.on('inputRead', () => {
+      this.editor.showHint()
+    })
+  },
+  methods: {
+    setVal() {
+      if (this.editor) {
+        if (this.value === '') {
+          this.editor.setValue('')
+        } else {
+          this.editor.setValue(this.value)
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.CodeMirror {
+  border: 1px solid black;
+  font-size: 13px;
+}
+
+// 这句为了解决匹配框显示有问题而加
+.CodeMirror-hints{
+  z-index: 9999 !important;
+}
+</style>

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

@@ -0,0 +1,62 @@
+<template>
+  <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
+  <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
+    <use :xlink:href="iconName" />
+  </svg>
+</template>
+
+<script>
+// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
+import { isExternal } from '@/utils/validate'
+
+export default {
+  name: 'SvgIcon',
+  props: {
+    iconClass: {
+      type: String,
+      required: true
+    },
+    className: {
+      type: String,
+      default: ''
+    }
+  },
+  computed: {
+    isExternal() {
+      return isExternal(this.iconClass)
+    },
+    iconName() {
+      return `#icon-${this.iconClass}`
+    },
+    svgClass() {
+      if (this.className) {
+        return 'svg-icon ' + this.className
+      } else {
+        return 'svg-icon'
+      }
+    },
+    styleExternalIcon() {
+      return {
+        mask: `url(${this.iconClass}) no-repeat 50% 50%`,
+        '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.svg-icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+
+.svg-external-icon {
+  background-color: currentColor;
+  mask-size: cover!important;
+  display: inline-block;
+}
+</style>

+ 175 - 0
src/components/ThemePicker/index.vue

@@ -0,0 +1,175 @@
+<template>
+  <el-color-picker
+    v-model="theme"
+    :predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
+    class="theme-picker"
+    popper-class="theme-picker-dropdown"
+  />
+</template>
+
+<script>
+const version = require('element-ui/package.json').version // element-ui version from node_modules
+const ORIGINAL_THEME = '#409EFF' // default color
+
+export default {
+  data () {
+    return {
+      chalk: '', // content of theme-chalk css
+      theme: ''
+    }
+  },
+  computed: {
+    defaultTheme () {
+      return this.$store.state.settings.theme
+    }
+  },
+  watch: {
+    defaultTheme: {
+      handler: function (val, oldVal) {
+        this.theme = val
+      },
+      immediate: true
+    },
+    async theme (val) {
+      const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
+      if (typeof val !== 'string') return
+      const themeCluster = this.getThemeCluster(val.replace('#', ''))
+      const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
+      console.log(themeCluster, originalCluster)
+
+      const $message = this.$message({
+        message: '  Compiling the theme',
+        customClass: 'theme-message',
+        type: 'success',
+        duration: 0,
+        iconClass: 'el-icon-loading'
+      })
+
+      const getHandler = (variable, id) => {
+        return () => {
+          const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
+          const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
+
+          let styleTag = document.getElementById(id)
+          if (!styleTag) {
+            styleTag = document.createElement('style')
+            styleTag.setAttribute('id', id)
+            document.head.appendChild(styleTag)
+          }
+          styleTag.innerText = newStyle
+        }
+      }
+
+      if (!this.chalk) {
+        const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
+        await this.getCSSString(url, 'chalk')
+      }
+
+      const chalkHandler = getHandler('chalk', 'chalk-style')
+
+      chalkHandler()
+
+      const styles = [].slice.call(document.querySelectorAll('style'))
+        .filter(style => {
+          const text = style.innerText
+          return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
+        })
+      styles.forEach(style => {
+        const { innerText } = style
+        if (typeof innerText !== 'string') return
+        style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
+      })
+
+      this.$emit('change', val)
+
+      $message.close()
+    }
+  },
+
+  methods: {
+    updateStyle (style, oldCluster, newCluster) {
+      let newStyle = style
+      oldCluster.forEach((color, index) => {
+        newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
+      })
+      return newStyle
+    },
+
+    getCSSString (url, variable) {
+      return new Promise(resolve => {
+        const xhr = new XMLHttpRequest()
+        xhr.onreadystatechange = () => {
+          if (xhr.readyState === 4 && xhr.status === 200) {
+            this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
+            resolve()
+          }
+        }
+        xhr.open('GET', url)
+        xhr.send()
+      })
+    },
+
+    getThemeCluster (theme) {
+      const tintColor = (color, tint) => {
+        let red = parseInt(color.slice(0, 2), 16)
+        let green = parseInt(color.slice(2, 4), 16)
+        let blue = parseInt(color.slice(4, 6), 16)
+
+        if (tint === 0) { // when primary color is in its rgb space
+          return [red, green, blue].join(',')
+        } else {
+          red += Math.round(tint * (255 - red))
+          green += Math.round(tint * (255 - green))
+          blue += Math.round(tint * (255 - blue))
+
+          red = red.toString(16)
+          green = green.toString(16)
+          blue = blue.toString(16)
+
+          return `#${red}${green}${blue}`
+        }
+      }
+
+      const shadeColor = (color, shade) => {
+        let red = parseInt(color.slice(0, 2), 16)
+        let green = parseInt(color.slice(2, 4), 16)
+        let blue = parseInt(color.slice(4, 6), 16)
+
+        red = Math.round((1 - shade) * red)
+        green = Math.round((1 - shade) * green)
+        blue = Math.round((1 - shade) * blue)
+
+        red = red.toString(16)
+        green = green.toString(16)
+        blue = blue.toString(16)
+
+        return `#${red}${green}${blue}`
+      }
+
+      const clusters = [theme]
+      for (let i = 0; i <= 9; i++) {
+        clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
+      }
+      clusters.push(shadeColor(theme, 0.1))
+      return clusters
+    }
+  }
+}
+</script>
+
+<style>
+.theme-message,
+.theme-picker-dropdown {
+  z-index: 99999 !important;
+}
+
+.theme-picker .el-color-picker__trigger {
+  height: 26px !important;
+  width: 26px !important;
+  padding: 2px;
+}
+
+.theme-picker-dropdown .el-color-dropdown__link-btn {
+  display: none;
+}
+</style>

+ 16 - 0
src/directive/flow/flowDel.js

@@ -0,0 +1,16 @@
+export default {
+  inserted(el, binding, vnode) {
+    const { value } = binding
+    // 工作流状态(1待提交,2已退回,3审核中,4通过,5不通过,6已撤销)
+    if (value) {
+      if (value === '1' || value === '6') {
+        el.disabled = false
+      } else {
+        el.disabled = true
+        el.classList.add('is-disabled')
+      }
+    } else {
+      throw new Error('请设置流程权限标签值')
+    }
+  }
+}

+ 16 - 0
src/directive/flow/flowEdit.js

@@ -0,0 +1,16 @@
+export default {
+  inserted(el, binding, vnode) {
+    const { value } = binding
+    // 工作流状态(1待提交,2已退回,3审核中,4通过,5不通过,6已撤销)
+    if (value) {
+      if (value === '1' || value === '2' || value === '6') {
+        el.disabled = false
+      } else {
+        el.disabled = true
+        el.classList.add('is-disabled')
+      }
+    } else {
+      throw new Error('请设置流程权限标签值')
+    }
+  }
+}

+ 15 - 0
src/directive/flow/index.js

@@ -0,0 +1,15 @@
+import flowEdit from './flowEdit'
+import flowDel from './flowDel'
+
+const install = function(Vue) {
+  Vue.directive('flowEdit', flowEdit)
+  Vue.directive('flowDel', flowDel)
+}
+
+if (window.Vue) {
+  window['flowEdit'] = flowEdit
+  window['flowDel'] = flowDel
+  Vue.use(install) // eslint-disable-line
+}
+
+export default install

+ 23 - 0
src/directive/permission/hasPerm.js

@@ -0,0 +1,23 @@
+import store from '@/store'
+
+export default {
+  inserted(el, binding, vnode) {
+    const { value } = binding
+    const allPermission = '*:*:*'
+    const permissions = store.getters && store.getters.user_perms
+
+    if (value && value instanceof Array && value.length > 0) {
+      const permissionFlag = value
+
+      const hasPermissions = permissions.some(permission => {
+        return allPermission === permission || permissionFlag.includes(permission)
+      })
+
+      if (!hasPermissions) {
+        el.parentNode && el.parentNode.removeChild(el)
+      }
+    } else {
+      throw new Error('请设置操作权限标签值')
+    }
+  }
+}

+ 23 - 0
src/directive/permission/hasRole.js

@@ -0,0 +1,23 @@
+import store from '@/store'
+
+export default {
+  inserted(el, binding, vnode) {
+    const { value } = binding
+    const superAdmin = 'admin'
+    const roles = store.getters && store.getters.user && store.getters.user.roles
+
+    if (value && value instanceof Array && value.length > 0) {
+      const roleFlag = value
+
+      const hasRole = roles.some(role => {
+        return superAdmin === role || roleFlag.includes(role)
+      })
+
+      if (!hasRole) {
+        el.parentNode && el.parentNode.removeChild(el)
+      }
+    } else {
+      throw new Error('请设置角色权限标签值')
+    }
+  }
+}

+ 15 - 0
src/directive/permission/index.js

@@ -0,0 +1,15 @@
+import hasRole from './hasRole'
+import hasPerm from './hasPerm'
+
+const install = function(Vue) {
+  Vue.directive('hasRole', hasRole)
+  Vue.directive('hasPerm', hasPerm)
+}
+
+if (window.Vue) {
+  window['hasRole'] = hasRole
+  window['hasPerm'] = hasPerm
+  Vue.use(install) // eslint-disable-line
+}
+
+export default install

+ 9 - 0
src/icons/index.js

@@ -0,0 +1,9 @@
+import Vue from 'vue'
+import SvgIcon from '@/components/SvgIcon'// svg component
+
+// register globally
+Vue.component('svg-icon', SvgIcon)
+
+const req = require.context('./svg', false, /\.svg$/)
+const requireAll = requireContext => requireContext.keys().map(requireContext)
+requireAll(req)

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

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1604911244621" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6868" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M160 896a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v448a32 32 0 0 1-32 32zM512 896a32 32 0 0 1-32-32V288a32 32 0 0 1 64 0v576a32 32 0 0 1-32 32zM864 896a32 32 0 0 1-32-32V160a32 32 0 0 1 64 0v704a32 32 0 0 1-32 32z" fill="#C0C5D3" p-id="6869"></path></svg>

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

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1604911239422" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6724" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M160 896a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v448a32 32 0 0 1-32 32zM512 896a32 32 0 0 1-32-32V288a32 32 0 0 1 64 0v576a32 32 0 0 1-32 32zM864 896a32 32 0 0 1-32-32V160a32 32 0 0 1 64 0v704a32 32 0 0 1-32 32z" fill="#4A8BFE" p-id="6725"></path></svg>

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

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1604911326427" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7739" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M928 512h-128a288 288 0 0 0-288-288V96a416 416 0 0 1 416 416z" fill="#C0C5D3" p-id="7740"></path><path d="M224 512H96A416 416 0 0 1 512 96v128a288 288 0 0 0-288 288z" fill="#9BA1B5" p-id="7741"></path><path d="M512 928A416 416 0 0 1 96 512h128a288 288 0 0 0 288 288z" fill="#C0C5D3" p-id="7742"></path><path d="M512 928v-128a288 288 0 0 0 288-288h128a416 416 0 0 1-416 416z" fill="#9BA1B5" p-id="7743"></path></svg>

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

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1604911320757" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7592" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M928 512h-128a288 288 0 0 0-288-288V96a416 416 0 0 1 416 416z" fill="#4A8BFE" p-id="7593"></path><path d="M224 512H96A416 416 0 0 1 512 96v128a288 288 0 0 0-288 288z" fill="#3BD5B3" p-id="7594"></path><path d="M512 928A416 416 0 0 1 96 512h128a288 288 0 0 0 288 288z" fill="#4A8BFE" p-id="7595"></path><path d="M512 928v-128a288 288 0 0 0 288-288h128a416 416 0 0 1-416 416z" fill="#3BD5B3" p-id="7596"></path></svg>

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.