zhuliu 1 gadu atpakaļ
revīzija
5bae0909c8
70 mainītis faili ar 27261 papildinājumiem un 0 dzēšanām
  1. 0 0
      .eslintrc.json
  2. 23 0
      .gitignore
  3. 0 0
      README.md
  4. 5 0
      babel.config.js
  5. 10 0
      jsconfig.json
  6. 13502 0
      package-lock.json
  7. 70 0
      package.json
  8. BIN
      public/favicon.ico
  9. 13 0
      public/index.html
  10. BIN
      public/logo.jpg
  11. 168 0
      src/App.vue
  12. 8 0
      src/api/index.js
  13. 5 0
      src/api/permission.js
  14. 31 0
      src/assets/css/fix.scss
  15. 120 0
      src/assets/css/layout.less
  16. 3 0
      src/assets/css/theme.css
  17. BIN
      src/assets/image/background.png
  18. BIN
      src/assets/image/background2.png
  19. BIN
      src/assets/image/login_background.jpg
  20. BIN
      src/assets/image/logo.jpg
  21. BIN
      src/assets/image/logo2.png
  22. BIN
      src/assets/image/logo3.png
  23. BIN
      src/assets/image/密码.png
  24. BIN
      src/assets/image/用户名.png
  25. BIN
      src/assets/media/yanshi.mp4
  26. 6 0
      src/config/index.js
  27. 6 0
      src/directives/permission.js
  28. 539 0
      src/icons/iconfont/demo.css
  29. 234 0
      src/icons/iconfont/demo_index.html
  30. 23 0
      src/icons/iconfont/iconfont.css
  31. 1 0
      src/icons/iconfont/iconfont.js
  32. 23 0
      src/icons/iconfont/iconfont.json
  33. BIN
      src/icons/iconfont/iconfont.ttf
  34. BIN
      src/icons/iconfont/iconfont.woff
  35. BIN
      src/icons/iconfont/iconfont.woff2
  36. 50 0
      src/main.js
  37. 60 0
      src/router/index.js
  38. 3 0
      src/store/getters.js
  39. 13 0
      src/store/index.js
  40. 23 0
      src/store/modules/user.js
  41. 128 0
      src/utils/axios.js
  42. 76 0
      src/utils/constants.js
  43. 53 0
      src/utils/file.js
  44. 134 0
      src/utils/formatTime.js
  45. 202 0
      src/utils/index.js
  46. 14 0
      src/utils/model/index.js
  47. 56 0
      src/utils/model/input/index.vue
  48. 10 0
      src/utils/permissions.js
  49. 33 0
      src/utils/storage.js
  50. 71 0
      src/views/home/components/downLoad/downLoad.vue
  51. 0 0
      src/views/home/components/downLoad/index.vue
  52. 21 0
      src/views/home/components/functionIntroduction/functionIntroduction.vue
  53. 0 0
      src/views/home/components/functionIntroduction/index.vue
  54. 21 0
      src/views/home/components/softwareSupport/index.vue
  55. 44 0
      src/views/home/components/softwareSupport/softwareSupport.vue
  56. 21 0
      src/views/home/components/version/index.vue
  57. 21 0
      src/views/home/components/version/version.vue
  58. 21 0
      src/views/home/components/videoDemo/index.vue
  59. 72 0
      src/views/home/components/videoDemo/videoDemo.vue
  60. 102 0
      src/views/home/index.vue
  61. 115 0
      src/views/home/index_old.vue
  62. 31 0
      src/views/index/index.vue
  63. 206 0
      src/views/layout/components/UserBar.vue
  64. 44 0
      src/views/layout/index.vue
  65. 25 0
      src/views/layout/mixins/index.js
  66. 110 0
      src/views/login/compoments/resePassword.vue
  67. 133 0
      src/views/login/index.vue
  68. 900 0
      src/views/user/index.vue
  69. 122 0
      vue.config.js
  70. 9536 0
      yarn.lock

+ 0 - 0
.eslintrc.json


+ 23 - 0
.gitignore

@@ -0,0 +1,23 @@
+.DS_Store
+node_modules
+/dist
+
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 0 - 0
README.md


+ 5 - 0
babel.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  presets: [
+    '@vue/cli-plugin-babel/preset'
+  ]
+}

+ 10 - 0
jsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./",
+    "paths": {
+      "@/*": [
+        "src/*"
+      ]
+    }
+  }
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 13502 - 0
package-lock.json


+ 70 - 0
package.json

@@ -0,0 +1,70 @@
+{
+  "name": "pas",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "build": "vue-cli-service build",
+    "lint": "vue-cli-service lint",
+    "dev": "vue-cli-service serve"
+  },
+  "dependencies": {
+    "@riophae/vue-treeselect": "^0.4.0",
+    "core-js": "^3.6.5",
+    "echarts": "^5.2.2",
+    "element-ui": "^2.15.7",
+    "html2canvas": "^1.3.3",
+    "js-cookie": "^3.0.1",
+    "less": "^4.1.2",
+    "less-loader": "^5.0.0",
+    "mockjs": "^1.1.0",
+    "moment": "^2.29.1",
+    "sass": "^1.43.4",
+    "sass-loader": "^9.0.3",
+    "sortablejs": "^1.14.0",
+    "vue": "^2.6.11",
+    "vue-router": "^3.2.0",
+    "vuex": "^3.4.0"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "~4.5.0",
+    "@vue/cli-plugin-eslint": "~4.5.0",
+    "@vue/cli-plugin-router": "~4.5.0",
+    "@vue/cli-plugin-vuex": "~4.5.0",
+    "@vue/cli-service": "~4.5.0",
+    "axios": "^0.18.0",
+    "babel-eslint": "^10.1.0",
+    "compression-webpack-plugin": "^5.0.2",
+    "eslint": "^6.7.2",
+    "eslint-plugin-vue": "^6.2.2",
+    "html-webpack-inline-source-plugin": "^0.0.10",
+    "lodash": "^4.17.21",
+    "pdfjs-dist": "^2.0.943",
+    "script-ext-html-webpack-plugin": "^2.1.5",
+    "spark-md5": "^3.0.2",
+    "svg-sprite-loader": "^6.0.11",
+    "vue-cli-plugin-axios": "^0.0.4",
+    "vue-cli-plugin-element": "^1.0.1",
+    "vue-particles": "^1.0.9",
+    "vue-pdf": "^4.3.0",
+    "vue-template-compiler": "^2.6.11"
+  },
+  "eslintConfig": {
+    "root": true,
+    "env": {
+      "node": true
+    },
+    "extends": [
+      "plugin:vue/essential",
+      "eslint:recommended"
+    ],
+    "parserOptions": {
+      "parser": "babel-eslint"
+    },
+    "rules": {}
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not dead"
+  ]
+}

BIN
public/favicon.ico


+ 13 - 0
public/index.html

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="">
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <link rel="icon" href="<%= BASE_URL %>logo.jpg">
+    <title><%= htmlWebpackPlugin.options.title %></title>
+</head>
+<body>
+<div id="app"></div>
+</body>
+</html>

BIN
public/logo.jpg


+ 168 - 0
src/App.vue

@@ -0,0 +1,168 @@
+<template>
+  <div id="app">
+    <router-view />
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'app',
+  components: {
+  },
+  created() {
+
+  },
+  mounted(){
+    var time = new Date(this.$c.updateTime).getTime()
+    var time2 = new Date().getTime()
+    if(time2 < time){
+        this.$router.push({path: '/'})
+        return false
+    }
+  },
+  methods: {
+
+  }
+}
+</script>
+
+<style lang="less">
+textarea {
+  font-family: 微软雅黑;
+}
+html, body, #app {
+  width: 100%;
+  height: 100%;
+  padding: 0;
+  margin: 0;
+  background: #f4f4f4;
+}
+.margin-left_0 {
+  margin-left: 0 !important;
+}
+.margin-top_10 {
+  margin-top: 10px !important;
+}
+.margin-left_10 {
+  margin-left: 10px !important;
+}
+.padding-left_10 {
+  padding-left: 10px;
+}
+.padding-right_10 {
+  padding-right: 10px;
+}
+.margin-left_20 {
+  margin-left: 20px;
+}
+.container-white-no-padding {
+  background: #fff !important;
+  padding: 0 !important;
+}
+.container-common-main {
+  background: #fff;
+  padding: 5px 20px !important;
+  margin-top: 20px !important;
+}
+.footer-common {
+  height: 70px !important;
+  text-align: right;
+}
+.margin-right_20 {
+  margin-right: 20px !important;
+}
+.width_100 {
+  width: 100% !important;
+}
+.margin-bottom_10 {
+  margin-bottom: 10px;
+}
+.float_right {
+  float: right
+}
+.float_left {
+  float: left;
+}
+.color-red {
+  color: red !important;
+}
+.color-black {
+  color: black;
+}
+.padding_0_5 {
+  padding: 0 5px;
+}
+.color-primary {
+  color: #409eff;
+}
+.margin-right_10 {
+  margin-right: 10px !important;
+}
+.text-align_center {
+  text-align: center !important;
+}
+.position_relative {
+  position: relative;
+}
+.no-body-padding-dialog {
+  .el-dialog__body {
+    padding: 0 !important;
+  }
+}
+.custom-table-header > th {
+  word-break: break-word;
+  background-color: #f8f8f9 !important;
+  color: #515a6e;
+  height: 40px;
+  font-size: 13px;
+}
+.el-header {
+  padding: 13px 0 !important;
+  .el-form {
+    .el-form-item {
+      margin-bottom: 0 !important
+    }
+  }
+}
+.custom-drawer-form {
+  .el-drawer__header {
+    padding: 0 20px !important;
+    margin: 15px 0 !important;
+    span {
+      font-size: 18px;
+      color: #303133;
+    }
+  }
+  .el-drawer__body {
+    border-top: 1px solid #e6e6e6;
+  }
+}
+.upload-file {
+  width: 100% !important;
+  .el-upload, .el-upload-dragger {
+    width: 100% !important;
+  }
+  .el-upload-dragger .el-icon-refresh {
+    font-size: 67px;
+    color: #C0C4CC;
+    margin: 40px 0 16px;
+    line-height: 50px;
+  }
+}
+.scrollable {-webkit-overflow-scrolling: touch;}
+::-webkit-scrollbar {width: 5px;height: 5px;}
+::-webkit-scrollbar-thumb {background-color: rgba(50, 50, 50, 0.3);}
+::-webkit-scrollbar-thumb:hover {background-color: rgba(50, 50, 50, 0.6);}
+::-webkit-scrollbar-track {background-color: rgba(50, 50, 50, 0.1);}
+::-webkit-scrollbar-track:hover {background-color: rgba(50, 50, 50, 0.2);}
+.el-aside {border-right: 1px solid #e6e6e6;background: #fff;}
+.el-header {background: #fff;border-bottom: 1px solid #e6e6e6;padding:13px 15px;display: flex;justify-content: space-between;align-items: center;}
+.el-header .left-panel {display: flex;align-items: center;}
+.el-header .right-panel {display: flex;align-items: center;}
+.el-header .right-panel > * + * {margin-left:10px;}
+.el-footer {background: #fff;border-top: 1px solid #e6e6e6;padding:13px 15px !important;}
+.el-main {padding:15px;}
+.el-main.nopadding {padding:0;background: #fff;}
+.el-main {flex-basis: 0}
+.el-container {height: 100%;}
+</style>

+ 8 - 0
src/api/index.js

@@ -0,0 +1,8 @@
+
+
+import permission from "./permission";
+
+export default {
+
+  ...permission
+}

+ 5 - 0
src/api/permission.js

@@ -0,0 +1,5 @@
+import axios from '@/utils/axios'
+
+export default {
+
+}

+ 31 - 0
src/assets/css/fix.scss

@@ -0,0 +1,31 @@
+/* 覆盖element-plus样式 */
+.el-menu {border: none!important;}
+.el-menu .el-menu-item a {color: inherit;text-decoration: none;display: block;width:100%;height:100%;position: absolute;top:0px;left:0px;}
+.el-form-item-msg {font-size: 12px;color: #999;clear: both;}
+.el-drawer__body {overflow: auto;padding:0;}
+.el-popconfirm__main {margin: 14px 0;}
+.el-card__header {border-bottom: 0;font-size: 17px;font-weight: bold;padding:15px 20px 0px 20px;}
+.el-dialog__title {font-size: 17px;font-weight: bold;}
+.el-drawer__header>:first-child {font-size: 17px;font-weight: bold;}
+.el-tree.menu .el-tree-node__content {height:36px;}
+.el-tree.menu .el-tree-node__content .el-tree-node__label .icon {margin-right: 5px;}
+.el-progress__text {font-size: 12px!important;}
+.el-progress__text i {font-size: 14.4px!important;}
+.el-step.is-horizontal .el-step__line {height:1px;}
+.el-step__title {font-size: 14px;}
+.drawerBG {background: #f6f8f9;}
+.el-button+.el-dropdown {margin-left: 10px;}
+.el-button-group+.el-dropdown {margin-left: 10px;}
+.el-tag+.el-tag {margin-left: 10px;}
+.el-button-group+.el-button-group {margin-left: 10px;}
+.el-tabs__nav-wrap::after {height: 1px;}
+.el-table th.is-sortable {transition: .1s;}
+.el-table th.is-sortable:hover {background: #eee;}
+.el-table .el-table__body-wrapper {background: #f6f8f9;}
+.el-col .el-card {margin-bottom: 15px;}
+.el-icon {font-size: inherit;}
+
+/* 覆盖tinymce样式 */
+.sceditor .tox-tinymce {border: 1px solid #DCDFE6;}
+.sceditor .tox .tox-statusbar {border-top: 1px solid #DCDFE6;}
+.sceditor .tox .tox-toolbar__primary {background: #f6f8f9;border-bottom: 1px solid #DCDFE6;}

+ 120 - 0
src/assets/css/layout.less

@@ -0,0 +1,120 @@
+.el-card__header {
+  padding: 10px 20px !important;
+  .card-header {
+    .el-form {
+      .el-form-item{
+        margin-bottom: 0 !important;
+      }
+    }
+  }
+}
+.pagination {
+  text-align: center;
+  margin: 20px 0;
+}
+.vue-treeselect__control {
+  padding-left: 10px !important;
+}
+.vue-treeselect__single-value {
+  padding-top: 3px !important;
+  color: #606266 !important;
+}
+.vue-treeselect__placeholder {
+  padding-top: 3px !important;
+}
+.el-input__inner {
+  color: #606266 !important;
+}
+.el-cascader-menu {
+  height: 350px !important;
+}
+.el-cascader-menu__wrap {
+  height: 100% !important;
+  overflow-x: hidden !important;
+}
+.sc-form-table .sc-form-table-handle {text-align: center;}
+.sc-form-table .sc-form-table-handle span {display: inline-block;}
+.sc-form-table .sc-form-table-handle button {display: none;}
+.sc-form-table .hover-row .sc-form-table-handle span {display: none;}
+.sc-form-table .hover-row .sc-form-table-handle button {display: inline-block;}
+.analyse-menu {
+  .el-menu {
+    border-right: 0 !important;
+  }
+  .el-scrollbar__wrap {
+    overflow-x: hidden !important;
+  }
+  .el-menu-item.is-active {
+    background: #ecf5ff !important;
+    color: #409EFF!important;
+  }
+}
+.chart-option {
+  position: fixed;
+  display: inline;
+  right: 40px;
+  top: 450px;
+  padding: 10px;
+  background-color: rgba(0, 0, 0, 0.35);
+  color: #fff;
+  cursor: pointer;
+  z-index: 999;
+  &:hover {
+    background: rgba(0, 0, 0, .5);
+  }
+}
+.search-option {
+  position: fixed;
+  display: inline;
+  right: 40px;
+  top: 450px;
+  padding: 10px;
+  background-color: rgba(0, 0, 0, 0.35);
+  color: #fff;
+  cursor: pointer;
+  z-index: 999;
+  &:hover {
+    background: rgba(0, 0, 0, .5);
+  }
+}
+.tree-item-tabs {
+  .el-tabs__header {
+    margin-top: 35px !important;
+    margin-left: 20px;
+  }
+}
+.chart-title {
+  padding: 20px;
+  span {
+    font-weight: bold;
+    font-size: 16px;
+  }
+}
+.box-card {
+  margin-bottom: 20px;
+  cursor: pointer;
+  .el-card__body {
+    padding: 0 !important;
+  }
+  .body {
+    padding: 20px;
+    font-size: 14px;
+  }
+  .active-right-box {
+    position: absolute;
+    right: 0;
+    top: 0;
+    width: 0;
+    height: 0;
+    border-left: 50px solid transparent;
+    border-top: 50px solid green;
+  }
+  .active-right-text {
+    position: absolute;
+    right: 0;
+    top: 10px;
+    font-size: 12px;
+    color: #fff;
+    transform: rotate(45deg);
+  }
+}

+ 3 - 0
src/assets/css/theme.css

@@ -0,0 +1,3 @@
+html{
+    --color:#494a9c; 
+}

BIN
src/assets/image/background.png


BIN
src/assets/image/background2.png


BIN
src/assets/image/login_background.jpg


BIN
src/assets/image/logo.jpg


BIN
src/assets/image/logo2.png


BIN
src/assets/image/logo3.png


BIN
src/assets/image/密码.png


BIN
src/assets/image/用户名.png


BIN
src/assets/media/yanshi.mp4


+ 6 - 0
src/config/index.js

@@ -0,0 +1,6 @@
+export default {
+    baseURL: "/api",
+    updateTime:'2023-08-04 08:00:00',
+    host: window.location.host,
+    staticURL: process.env.NODE_ENV === 'production' ? 'http://192.168.0.7:8081' : 'http://192.168.0.7:8081',
+}

+ 6 - 0
src/directives/permission.js

@@ -0,0 +1,6 @@
+import axios from '@/utils/axios'
+import Store from '@/store'
+
+
+export const hasPermission = (sign) => {
+}

+ 539 - 0
src/icons/iconfont/demo.css

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

+ 234 - 0
src/icons/iconfont/demo_index.html

@@ -0,0 +1,234 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8"/>
+  <title>iconfont Demo</title>
+  <link rel="shortcut icon" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg" type="image/x-icon"/>
+  <link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg"/>
+  <link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
+  <link rel="stylesheet" href="demo.css">
+  <link rel="stylesheet" href="iconfont.css">
+  <script src="iconfont.js"></script>
+  <!-- jQuery -->
+  <script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
+  <!-- 代码高亮 -->
+  <script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
+  <style>
+    .main .logo {
+      margin-top: 0;
+      height: auto;
+    }
+
+    .main .logo a {
+      display: flex;
+      align-items: center;
+    }
+
+    .main .logo .sub-title {
+      margin-left: 0.5em;
+      font-size: 22px;
+      color: #fff;
+      background: linear-gradient(-45deg, #3967FF, #B500FE);
+      -webkit-background-clip: text;
+      -webkit-text-fill-color: transparent;
+    }
+  </style>
+</head>
+<body>
+  <div class="main">
+    <h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
+      <img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
+      
+    </a></h1>
+    <div class="nav-tabs">
+      <ul id="tabs" class="dib-box">
+        <li class="dib active"><span>Unicode</span></li>
+        <li class="dib"><span>Font class</span></li>
+        <li class="dib"><span>Symbol</span></li>
+      </ul>
+      
+      <a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=4690301" target="_blank" class="nav-more">查看项目</a>
+      
+    </div>
+    <div class="tab-container">
+      <div class="content unicode" style="display: block;">
+          <ul class="icon_lists dib-box">
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe62c;</span>
+                <div class="name">密码</div>
+                <div class="code-name">&amp;#xe62c;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe614;</span>
+                <div class="name">用户名</div>
+                <div class="code-name">&amp;#xe614;</div>
+              </li>
+          
+          </ul>
+          <div class="article markdown">
+          <h2 id="unicode-">Unicode 引用</h2>
+          <hr>
+
+          <p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
+          <ul>
+            <li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
+            <li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
+          </ul>
+          <blockquote>
+            <p>注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
+          </blockquote>
+          <p>Unicode 使用步骤如下:</p>
+          <h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
+<pre><code class="language-css"
+>@font-face {
+  font-family: 'iconfont';
+  src: url('iconfont.woff2?t=1726826444037') format('woff2'),
+       url('iconfont.woff?t=1726826444037') format('woff'),
+       url('iconfont.ttf?t=1726826444037') format('truetype');
+}
+</code></pre>
+          <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
+<pre><code class="language-css"
+>.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+</code></pre>
+          <h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
+<pre>
+<code class="language-html"
+>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
+</code></pre>
+          <blockquote>
+            <p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
+          </blockquote>
+          </div>
+      </div>
+      <div class="content font-class">
+        <ul class="icon_lists dib-box">
+          
+          <li class="dib">
+            <span class="icon iconfont icon-mima"></span>
+            <div class="name">
+              密码
+            </div>
+            <div class="code-name">.icon-mima
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-yonghuming"></span>
+            <div class="name">
+              用户名
+            </div>
+            <div class="code-name">.icon-yonghuming
+            </div>
+          </li>
+          
+        </ul>
+        <div class="article markdown">
+        <h2 id="font-class-">font-class 引用</h2>
+        <hr>
+
+        <p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
+        <p>与 Unicode 使用方式相比,具有如下特点:</p>
+        <ul>
+          <li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
+          <li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
+        </ul>
+        <p>使用步骤如下:</p>
+        <h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
+<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
+</code></pre>
+        <h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
+<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
+</code></pre>
+        <blockquote>
+          <p>"
+            iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
+        </blockquote>
+      </div>
+      </div>
+      <div class="content symbol">
+          <ul class="icon_lists dib-box">
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-mima"></use>
+                </svg>
+                <div class="name">密码</div>
+                <div class="code-name">#icon-mima</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-yonghuming"></use>
+                </svg>
+                <div class="name">用户名</div>
+                <div class="code-name">#icon-yonghuming</div>
+            </li>
+          
+          </ul>
+          <div class="article markdown">
+          <h2 id="symbol-">Symbol 引用</h2>
+          <hr>
+
+          <p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
+            这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
+          <ul>
+            <li>支持多色图标了,不再受单色限制。</li>
+            <li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
+            <li>兼容性较差,支持 IE9+,及现代浏览器。</li>
+            <li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
+          </ul>
+          <p>使用步骤如下:</p>
+          <h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
+<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
+</code></pre>
+          <h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
+<pre><code class="language-html">&lt;style&gt;
+.icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+&lt;/style&gt;
+</code></pre>
+          <h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
+<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
+  &lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
+&lt;/svg&gt;
+</code></pre>
+          </div>
+      </div>
+
+    </div>
+  </div>
+  <script>
+  $(document).ready(function () {
+      $('.tab-container .content:first').show()
+
+      $('#tabs li').click(function (e) {
+        var tabContent = $('.tab-container .content')
+        var index = $(this).index()
+
+        if ($(this).hasClass('active')) {
+          return
+        } else {
+          $('#tabs li').removeClass('active')
+          $(this).addClass('active')
+
+          tabContent.hide().eq(index).fadeIn()
+        }
+      })
+    })
+  </script>
+</body>
+</html>

+ 23 - 0
src/icons/iconfont/iconfont.css

@@ -0,0 +1,23 @@
+@font-face {
+  font-family: "iconfont"; /* Project id 4690301 */
+  src: url('iconfont.woff2?t=1726826444037') format('woff2'),
+       url('iconfont.woff?t=1726826444037') format('woff'),
+       url('iconfont.ttf?t=1726826444037') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-mima:before {
+  content: "\e62c";
+}
+
+.icon-yonghuming:before {
+  content: "\e614";
+}
+

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 0
src/icons/iconfont/iconfont.js


+ 23 - 0
src/icons/iconfont/iconfont.json

@@ -0,0 +1,23 @@
+{
+  "id": "4690301",
+  "name": "qiaoPen",
+  "font_family": "iconfont",
+  "css_prefix_text": "icon-",
+  "description": "",
+  "glyphs": [
+    {
+      "icon_id": "5532892",
+      "name": "密码",
+      "font_class": "mima",
+      "unicode": "e62c",
+      "unicode_decimal": 58924
+    },
+    {
+      "icon_id": "6884425",
+      "name": "用户名",
+      "font_class": "yonghuming",
+      "unicode": "e614",
+      "unicode_decimal": 58900
+    }
+  ]
+}

BIN
src/icons/iconfont/iconfont.ttf


BIN
src/icons/iconfont/iconfont.woff


BIN
src/icons/iconfont/iconfont.woff2


+ 50 - 0
src/main.js

@@ -0,0 +1,50 @@
+import Vue from 'vue'
+import './utils/axios'
+import App from './App.vue'
+import router from './router'
+import store from './store'
+import constants from './utils/constants'
+import Element from 'element-ui'
+import 'element-ui/lib/theme-chalk/index.css'
+import api from './api'
+import * as echarts from 'echarts'
+// import Charts from './views/analyse/custom/components/Charts'
+import Particles from 'vue-particles'
+import { formatTableDate } from "./utils";
+import Config from './config'
+import Storage from './utils/storage'
+import { hasRole } from './utils/permissions'
+require('./assets/css/fix.scss')
+require('./assets/css/layout.less')
+require('./assets/css/theme.css')
+import "@/icons/iconfont/iconfont.css"
+import lodash from 'lodash'
+
+import {hasPermission} from './directives/permission';
+Vue.prototype.$permission = hasPermission
+// import Directives from './directives/index'
+// Vue.use(Directives)
+
+//组件库
+import model from './utils/model'
+Vue.use(model)
+
+Vue.config.productionTip = false
+Vue.prototype.$constants = constants
+Vue.prototype.$api = api
+// Vue.prototype.$echarts = echarts
+Vue.prototype.$d = formatTableDate
+Vue.prototype.$p = Config.staticURL
+Vue.prototype.$c = Config
+Vue.prototype.$s = Storage
+Vue.prototype.$_ = lodash
+Vue.prototype.$r = hasRole
+// Vue.use(Charts)
+Vue.use(Particles)
+Vue.use(Element)
+
+new Vue({
+  router,
+  store,
+  render: h => h(App)
+}).$mount('#app')

+ 60 - 0
src/router/index.js

@@ -0,0 +1,60 @@
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+
+Vue.use(VueRouter)
+
+const originalPush = VueRouter.prototype.push
+VueRouter.prototype.push = function push(location) {
+  return originalPush.call(this, location).catch(err => err)
+}
+const routes = [
+  {
+    path: "/",
+    component: () => import('@/views/index'),
+  },
+
+  // {
+  //   path:'/login',
+  //   name:'Login',
+  //   meta: {
+  //     title: '系统登录'
+  //   },
+  //   component: () => import("@/views/login/index.vue")
+  // },
+  {
+    path: "",
+    component: () => import('@/views/layout/index.vue'),
+    children: [
+      {
+        path: '/home',
+        name: 'Home',
+        meta: {
+          // title: '首页',
+          sign: 'home',
+          belong: 'home'
+        },
+        component: () => import('@/views/home/index.vue'),
+      },
+    ]
+  }
+ 
+]
+
+const router = new VueRouter({
+  mode: 'history',
+  base: '/',
+  routes
+})
+
+router.beforeEach((to, from, next) => {
+  if (to.meta.title) {
+    document.title = to.meta.title;
+  }
+  next();
+})
+
+router.afterEach((to, from) => {
+
+});
+
+export default router

+ 3 - 0
src/store/getters.js

@@ -0,0 +1,3 @@
+export default {
+  userinfo: state => state.user.userinfo,
+}

+ 13 - 0
src/store/index.js

@@ -0,0 +1,13 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+import user from './modules/user'
+import getters from './getters'
+
+Vue.use(Vuex)
+
+export default new Vuex.Store({
+  modules: {
+    user,
+  },
+  getters
+})

+ 23 - 0
src/store/modules/user.js

@@ -0,0 +1,23 @@
+import storage from '@/utils/storage'
+import constants from "@/utils/constants";
+import Api from '@/api'
+
+export default {
+  state: {
+    userinfo: storage.getObj(constants.userinfo),
+  },
+
+  mutations: {
+    SET_USERINFO: (state, userinfo) => {
+      state.userinfo = userinfo
+      storage.setObj(constants.userinfo, userinfo)
+    },
+    
+  },
+
+  actions: {
+    getCurrentGenFileNum({ commit }) {
+        commit('SET_CURRENT_NUM', [])
+    },
+  }
+}

+ 128 - 0
src/utils/axios.js

@@ -0,0 +1,128 @@
+"use strict";
+
+import Vue from 'vue';
+import axios from "axios";
+import constants from "@/utils/constants";
+import storage from "@/utils/storage";
+import { Notification, Loading } from 'element-ui'
+import Store from '@/store'
+import Api from '@/api'
+import Config from '@/config'
+import Router from '@/router'
+
+// Full config:  https://github.com/axios/axios#request-config
+// axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || '';
+// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
+// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
+
+// 是否正在刷新的标记
+let isRefreshing = false
+// 重试队列,每一项将是一个待执行的函数形式
+let retryRequests = []
+let loadingInstance = {}
+let config = {
+  baseURL: Config.baseURL
+  // timeout: 60 * 1000, // Timeout
+  // withCredentials: true, // Check cross-site Access-Control
+};
+
+const _axios = axios.create(config);
+
+_axios.interceptors.request.use(
+  function (config) {
+    // Do something before request is sent
+    const token = storage.getStr(constants.token)
+    if (token) {
+      // config.headers[constants.tokenHeader] = token
+    }
+    config.headers['x-project-id'] = Store.getters.projectId || ''
+    if (config.loading) {
+      loadingInstance = Loading.service({})
+    }
+    // console.log(config)
+    return config;
+  },
+  function (error) {
+    // Do something with request error
+    return Promise.reject(error);
+  }
+);
+
+// Add a response interceptor
+_axios.interceptors.response.use(
+  function (response) {
+    const config = response.config
+    if (config.loading) {
+      loadingInstance.close()
+    }
+    let { code, message } = response.data
+    if (code === 200 || config.responseType === 'blob') {
+      isRefreshing = false
+      return response.data
+    }
+    if (code === 401) {
+      Router.push({
+        path: `${Store.getters.prefix}/login`
+      }).then(r => {})
+      return Promise.reject(response.data)
+    }
+    if (code === 402) {
+      Notification.error({
+        title: '权限不足',
+        message: message
+      })
+      return Promise.reject(response.data)
+    }
+    if(code == 806){
+      Notification.error({
+        title: '账号未启用',
+        message: message
+      })
+      return Promise.reject(response.data)
+    }
+    if (code === 500) {
+      // TODO
+      return Promise.reject(response.data)
+    } else if (code === 0) {
+      isRefreshing = false
+      Notification.error({
+        title: '请求错误',
+        message: message
+      })
+      return Promise.reject(response.data)
+    } else if (code !== 401) {
+    }
+    // Do something with response data
+    // return response;
+  },
+  function (error) {
+    // Do something with response error
+    Notification.error({
+      title: '系统错误',
+      message: error.response.data.message
+    })
+    isRefreshing = false
+    return Promise.reject(error);
+  }
+);
+
+Plugin.install = function (Vue) {
+  Vue.axios = _axios;
+  window.axios = _axios;
+  Object.defineProperties(Vue.prototype, {
+    axios: {
+      get() {
+        return _axios;
+      }
+    },
+    $axios: {
+      get() {
+        return _axios;
+      }
+    },
+  });
+};
+
+Vue.use(Plugin)
+
+export default _axios;

+ 76 - 0
src/utils/constants.js

@@ -0,0 +1,76 @@
+export default {
+  tokenHeader: "Authorization",
+  token: "token",
+  projectId: "projectId",
+  userinfo: "userinfo",
+  prefix: "prefix",
+  permissions: [
+    { label: '公用', value: 2, class: 'success' },
+    { label: '指定专题库', value: 1, class: 'danger' },
+  ],
+  patentType: [
+    { label: '实用新型', value: 1, class: 'primary' },
+    { label: '发明申请', value: 2, class: 'success' },
+    { label: '外观设计', value: 3, class: 'warning' },
+    { label: '授权发明', value: 4, class: 'danger' },
+  ],
+  patentSimpleStatus: [
+    { label: '审中', value: 1, class: 'primary' },
+    { label: '失效', value: 2, class: 'danger' },
+    { label: '有效', value: 3, class: 'success' },
+    { label: 'PCT状态', value: 4, class: 'warning' },
+    { label: 'PCT指定期满', value: 5, class: 'warning' },
+    { label: 'PCT指定期内', value: 6, class: 'warning' },
+  ],
+  templateLabelType: [
+    { label: '系统数据', value: 0, class: '', object: 'sys.', symbol: '{{?}}' },
+    { label: '专题库信息', value: 1, class: '', object: 'thematic.', symbol: '{{?}}' },
+    { label: '专利信息', value: 2, class: '', object: '', symbol: '?' },
+    { label: '专利法律状态', value: 3, class: '', object: 'sys.', symbol: '{{?}}' },
+    { label: '专利申请人', value: 4, class: '', object: 'sys.', symbol: '{{?}}' },
+    { label: '合并申请人', value: 5, class: '', object: 'sys.', symbol: '{{?}}' },
+    { label: '许可人', value: 6, class: '', object: 'sys.', symbol: '{{?}}' },
+    { label: '被许可人', value: 7, class: '', object: 'sys.', symbol: '{{?}}' },
+  ],
+  /**
+   * type = 1 单维度矩阵数据
+   * type = 2 多维度矩阵数据
+   * type = 3 树形数据
+   */
+  chartType: [
+    { label: '单折线图', value: 1, type: 1, component: 'CLine', icon: 'line' },
+    { label: '多折线图', value: 2, type: 2, component: 'CMultipleLine', icon: 'multipleLine' },
+    { label: '面积图', value: 3, type: 1, component: 'CArea', icon: 'area' },
+    { label: '柱形图', value: 4, type: 1, component: 'CBar', icon: 'bar' },
+    { label: '堆积柱形图', value: 5, type: 2, component: 'CStackedBar', icon: 'stackedBar' },
+    { label: '簇状柱形图', value: 6, type: 2, component: 'CMultipleBar', icon: 'multipleBar' },
+    { label: '条形图', value: 7, type: 1, component: 'CColumn', icon: 'column' },
+    { label: '堆积条形图', value: 8, type: 2, component: 'CStackedColumn', icon: 'stackedColumn' },
+    { label: '簇状条形图', value: 9, type: 2, component: 'CMultipleColumn', icon: 'multipleColumn' },
+    { label: '环形图', value: 10, type: 1, component: 'CDoughnut', icon: 'doughnut' },
+    { label: '饼图', value: 11, type: 1, component: 'CPie', icon: 'pie' },
+    { label: '旭日图', value: 12, type: 2, component: 'CSunburst', icon: 'sunburst' },
+    { label: '矩形树形图', value: 13, type: 2, component: 'CTreemap', icon: 'tree' },
+    { label: '热力图', value: 14, type: 2, component: 'CHeat', icon: 'heat' },
+    { label: '气泡图', value: 15, type: 2, component: 'CScatter', icon: 'scatter' },
+    { label: '雷达图', value: 17, type: 2, component: 'CRadar', icon: 'radar' },
+    { label: '雷达图(分离)', value: 22, type: 2, component: 'CRadar2', icon: 'radar2' },
+    { label: '全球', value: 18, type: 1, component: 'CMap', icon: 'map' },
+    { label: '中国', value: 23, type: 1, component: 'CMap1', icon: 'map2' },
+    { label: '中国(省)', value: 21, type: 1, component: 'CMap2', icon: 'cite' },
+    { label: '桑基图', value: 19, type: 2, component: 'CSankey', icon: 'sankey' },
+    { label: '树图', value: 20, type: 3, component: 'CTree', icon: 'tree2' },
+    { label: '表格', value: 30, type: 2, component: 'CTable', icon: 'table' },
+  ],
+  /**
+   * 坐标轴字体
+   */
+  fontFamily: [
+    { label: 'sans-serif', value: 'sans-serif' },
+    { label: 'serif', value: 'serif' },
+    { label: 'monospace', value: 'monospace' },
+    { label: 'Arial', value: 'Arial' },
+    { label: 'Courier New', value: 'Courier New' },
+    { label: 'Microsoft YaHei', value: 'Microsoft YaHei' },
+  ],
+}

+ 53 - 0
src/utils/file.js

@@ -0,0 +1,53 @@
+import SparkMD5 from 'spark-md5'
+
+const chunkSize = 10 * 1024 * 1024
+/**
+ * 分片读取文件 MD5
+ */
+export const getFileMD5 = (file, callback) => {
+  const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
+  const fileReader = new FileReader()
+  // 计算分片数
+  const totalChunks = Math.ceil(file.size / chunkSize)
+  // console.log('总分片数:' + totalChunks)
+  let currentChunk = 0
+  const spark = new SparkMD5.ArrayBuffer()
+  loadNext()
+  fileReader.onload = function (e) {
+    try {
+      spark.append(e.target.result)
+    } catch (error) {
+      // console.log('获取Md5错误:' + currentChunk)
+    }
+    if (currentChunk < totalChunks) {
+      currentChunk++
+      loadNext()
+    } else {
+      callback(spark.end())
+    }
+  }
+  fileReader.onerror = function () {
+    console.warn('读取Md5失败,文件读取错误')
+  }
+
+  function loadNext() {
+    const start = currentChunk * chunkSize
+    const end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize
+    // 注意这里的 fileRaw
+    fileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
+  }
+}
+/**
+ * 文件分片
+ */
+export const createFileChunk = (file) => {
+  const fileChunkList = []
+  let count = 0
+  while (count < file.size) {
+    fileChunkList.push({
+      file: file.slice(count, count + chunkSize),
+    })
+    count += chunkSize
+  }
+  return fileChunkList
+}

+ 134 - 0
src/utils/formatTime.js

@@ -0,0 +1,134 @@
+/*
+ * 年(Y) 可用1-4个占位符
+ * 月(m)、日(d)、小时(H)、分(M)、秒(S) 可用1-2个占位符
+ * 星期(W) 可用1-3个占位符
+ * 季度(q为阿拉伯数字,Q为中文数字)可用1或4个占位符
+ *
+ * let date = new Date()
+ * formatDate(date, "YYYY-mm-dd HH:MM:SS")           // 2020-02-09 14:04:23
+ * formatDate(date, "YYYY-mm-dd HH:MM:SS Q")         // 2020-02-09 14:09:03 一
+ * formatDate(date, "YYYY-mm-dd HH:MM:SS WWW")       // 2020-02-09 14:45:12 星期日
+ * formatDate(date, "YYYY-mm-dd HH:MM:SS QQQQ")      // 2020-02-09 14:09:36 第一季度
+ * formatDate(date, "YYYY-mm-dd HH:MM:SS WWW QQQQ")  // 2020-02-09 14:46:12 星期日 第一季度
+ */
+export function formatDate(date, format) {
+    let we = date.getDay(); // 星期
+    let qut = Math.floor((date.getMonth() + 3) / 3).toString(); // 季度
+    const opt = {
+        'Y+': date.getFullYear().toString(), // 年
+        'm+': (date.getMonth() + 1).toString(), // 月(月份从0开始,要+1)
+        'd+': date.getDate().toString(), // 日
+        'H+': date.getHours().toString(), // 时
+        'M+': date.getMinutes().toString(), // 分
+        'S+': date.getSeconds().toString(), // 秒
+        'q+': qut, // 季度
+    };
+    const week = {
+        // 中文数字 (星期)
+        '0': '日',
+        '1': '一',
+        '2': '二',
+        '3': '三',
+        '4': '四',
+        '5': '五',
+        '6': '六',
+    };
+    const quarter = {
+        // 中文数字(季度)
+        '1': '一',
+        '2': '二',
+        '3': '三',
+        '4': '四',
+    };
+    if (/(W+)/.test(format)) {
+        format = format.replace(RegExp.$1, RegExp.$1.length > 1 ? (RegExp.$1.length > 2 ? '星期' + week[we] : '周' + week[we]) : week[we]);
+    }
+    if (/(Q+)/.test(format)) {
+        // 输入一个Q,只输出一个中文数字,输入4个Q,则拼接上字符串
+        format = format.replace(RegExp.$1, RegExp.$1.length == 4 ? '第' + quarter[qut] + '季度' : quarter[qut]);
+    }
+    for (let k in opt) {
+        let r = new RegExp('(' + k + ')').exec(format);
+        if (r) {
+            // 若输入的长度不为1,则前面补零
+            format = format.replace(r[1], RegExp.$1.length == 1 ? opt[k] : opt[k].padStart(RegExp.$1.length, '0'));
+        }
+    }
+    return format;
+}
+
+/**
+ * 10秒:  10 * 1000
+ * 1分:   60 * 1000
+ * 1小时: 60 * 60 * 1000
+ * 24小时:60 * 60 * 24 * 1000
+ * 3天:   60 * 60* 24 * 1000 * 3
+ *
+ * let data = new Date()
+ * formatPast(data)                                           // 刚刚
+ * formatPast(data - 11 * 1000)                               // 11秒前
+ * formatPast(data - 2 * 60 * 1000)                           // 2分钟前
+ * formatPast(data - 60 * 60 * 2 * 1000)                      // 2小时前
+ * formatPast(data - 60 * 60 * 2 * 1000)                      // 2小时前
+ * formatPast(data - 60 * 60 * 71 * 1000)                     // 2天前
+ * formatPast("2020-06-01")                                   // 2020-06-01
+ * formatPast("2020-06-01", "YYYY-mm-dd HH:MM:SS WWW QQQQ")   // 2020-06-01 08:00:00 星期一 第二季度
+ */
+export function formatPast(param, format = 'YYYY-mm-dd') {
+    // 传入格式处理、存储转换值
+    let t, s;
+    // 获取js 时间戳
+    let time = new Date().getTime();
+    // 是否是对象
+    typeof param === 'string' || 'object' ? (t = new Date(param).getTime()) : (t = param);
+    // 当前时间戳 - 传入时间戳
+    time = Number.parseInt(time - t);
+    if (time < 10000) {
+        // 10秒内
+        return '刚刚';
+    } else if (time < 60000 && time >= 10000) {
+        // 超过10秒少于1分钟内
+        s = Math.floor(time / 1000);
+        return `${s}秒前`;
+    } else if (time < 3600000 && time >= 60000) {
+        // 超过1分钟少于1小时
+        s = Math.floor(time / 60000);
+        return `${s}分钟前`;
+    } else if (time < 86400000 && time >= 3600000) {
+        // 超过1小时少于24小时
+        s = Math.floor(time / 3600000);
+        return `${s}小时前`;
+    } else if (time < 259200000 && time >= 86400000) {
+        // 超过1天少于3天内
+        s = Math.floor(time / 86400000);
+        return `${s}天前`;
+    } else {
+        // 超过3天
+        let date = typeof param === 'string' || 'object' ? new Date(param) : param;
+        return formatDate(date, format);
+    }
+}
+
+/**
+ * formatAxis(new Date())   // 上午好
+ */
+export function formatAxis(param) {
+    let hour = new Date(param).getHours();
+    if (hour < 6) {
+        return '凌晨好';
+    } else if (hour < 9) {
+        return '早上好';
+    } else if (hour < 12) {
+        return '上午好';
+    } else if (hour < 14) {
+        return '中午好';
+    } else if (hour < 17) {
+        return '下午好';
+    } else if (hour < 19) {
+        return '傍晚好';
+    } else if (hour < 22) {
+        return '晚上好';
+    } else {
+        return '夜里好';
+    }
+}

+ 202 - 0
src/utils/index.js

@@ -0,0 +1,202 @@
+import moment from 'moment'
+import _ from 'lodash'
+import constants from '@/utils/constants'
+
+export const formatDate = (date, format = 'YYYY-MM-DD') => {
+  return moment(date).format(format)
+}
+
+export const formatTableDate = (dateTime, format = 'YYYY-MM-DD HH:mm:ss') => {
+  if (dateTime === 0) {
+    return ''
+  }
+  return moment(new Date(dateTime * 1000)).format(format)
+}
+
+export const downLoad = (data, fileName) => {
+  let blob = new Blob([data], {type: 'application/force-download'});
+  let objectUrl = URL.createObjectURL(blob);
+  let element = document.createElement('a');
+  element.setAttribute('href', objectUrl);
+  element.setAttribute('download', fileName);
+  document.body.appendChild(element);
+  element.click();
+  document.body.removeChild(element);
+}
+
+export const getFileName = (type) => {
+  return moment().format('YYYYMMDDHHmmss') + '.' + type
+}
+
+export const downLoadBase64 = (content, fileName) => {
+  let base64ToBlob = function (code) {
+    let parts = code.split(';base64,');
+    let contentType = parts[0].split(':')[1];
+    let raw = window.atob(parts[1]);
+    let rawLength = raw.length;
+    let uInt8Array = new Uint8Array(rawLength);
+    for (let i = 0; i < rawLength; ++i) {
+      uInt8Array[i] = raw.charCodeAt(i);
+    }
+    return new Blob([uInt8Array], {
+      type: contentType
+    });
+  };
+  let aLink = document.createElement('a');
+  let blob = base64ToBlob(content);
+  let evt = document.createEvent("HTMLEvents");
+  evt.initEvent("click", true, true);
+  aLink.download = fileName;
+  aLink.href = URL.createObjectURL(blob);
+  aLink.click();
+}
+
+export const downLoad2 = (url) => {
+  const href = `/api/v2/common/download?url=${encodeURIComponent(url)}`
+  const anchor = document.createElement('a');
+  const fileName = 'download';
+  if ('download' in anchor) {
+    anchor.href = href;
+    anchor.setAttribute("download", fileName);
+    anchor.className = "download-js-link";
+    anchor.innerHTML = "downloading...";
+    anchor.style.display = "none";
+    document.body.appendChild(anchor);
+    setTimeout(function () {
+      anchor.click();
+      document.body.removeChild(anchor);
+    }, 66);
+    return true;
+  }
+}
+
+export const findChildren = (arr, fn, result = []) => {
+  arr.forEach(item => {
+    if (item.children && item.children.length) {
+      findChildren(item.children, fn, result)
+    } else {
+      if (fn(item)) {
+        result.push(item)
+      }
+    }
+  })
+  return result
+}
+
+export const setChildren = (arr, key, value) => {
+  arr.forEach(item => {
+    if (item.children && item.children.length) {
+      setChildren(item.children, key, value)
+    } else {
+      item[key] = value
+    }
+  })
+  return arr
+}
+
+export const random = (min, max) => {
+  return Math.floor(Math.random() * (max - min)) + min;
+}
+
+export const getRandomArrayElements = (arr, count) => {
+  let shuffled = arr.slice(0), i = arr.length, min = i - count, temp, index;
+  if (min < 0) {
+    min = 0
+  }
+  while (i-- > min) {
+    index = Math.floor((i + 1) * Math.random());
+    temp = shuffled[index];
+    shuffled[index] = shuffled[i];
+    shuffled[i] = temp;
+  }
+  return shuffled.slice(min);
+}
+
+export const getTreeDataList = (treeList, arr) => {
+  for (let i = 0; i < treeList.length; i++) {
+    arr.push(treeList[i])
+    if (treeList[i].children && treeList[i].children.length) {
+      getTreeDataList(treeList[i].children, arr)
+    }
+  }
+  return arr
+}
+
+export const getTreeLastChildren = (treeList, arr) => {
+  for (let i = 0; i < treeList.length; i++) {
+    if (treeList[i].children && treeList[i].children.length) {
+      getTreeLastChildren(treeList[i].children, arr)
+    } else {
+      arr.push(treeList[i])
+    }
+  }
+  return arr
+}
+
+export const handleTree = (data) => {
+  data.forEach(function (item) {
+    delete item.children
+  })
+  let map = {}
+  data.forEach(function (item) {
+    map[item.id] = item
+  })
+  let val = []
+  data.forEach(function (item) {
+    let parent = map[item.parentId]
+    if (parent) {
+      (parent.children || (parent.children = [])).push(item)
+    } else {
+      val.push(item)
+    }
+  })
+  return val
+}
+
+export const getTotalPage = (total, size) => {
+  return Math.ceil(total / size)
+}
+
+export const findTreeEq = (treeList, key) => {
+  const dataList = getTreeDataList(treeList, [])
+  const parentId = _.uniq(dataList.map(item => item.parentId))
+  let dataObj = {}
+  if (dataList.length === 0) {
+    return '请添加选项'
+  }
+  if (!dataList.map(item => item.name).every(item => !!item)) {
+    return '选项不能为空'
+  }
+  parentId.map(id => {
+    dataObj[id] = dataList.filter(item => item.parentId === id).map(item => item.name)
+  })
+  for (let data in dataObj) {
+    if (dataObj[data].length !== _.uniq(dataObj[data]).length) {
+      let name = ''
+      if (parseInt(data) === 0) {
+        name = '主'
+      } else {
+        name = dataList.find(item => item.id === parseInt(data)).name
+      }
+      return `${name}节点名称重复`
+    }
+  }
+  return false;
+}
+
+export const renderSize = (value) => {
+  if (null === value || value === '') {
+    return "0 Bytes";
+  }
+  const unitArr = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
+  let index = 0;
+  let srcSize = parseFloat(value);
+  index = Math.floor(Math.log(srcSize) / Math.log(1024));
+  let size = srcSize / Math.pow(1024, index);
+  size = size.toFixed(2);
+  return size + unitArr[index];
+}
+
+export const getPatentCountry = (patentNo) => {
+  return patentNo.substr(0, 2)
+}

+ 14 - 0
src/utils/model/index.js

@@ -0,0 +1,14 @@
+// 全局注册自定义
+
+import myInput from './input/index.vue'
+
+var models = {
+  myInput
+}
+export default {
+  install(Vue) {
+      Object.keys(models).forEach((key) => {
+        Vue.component(key, models[key]);
+      });
+  },
+};

+ 56 - 0
src/utils/model/input/index.vue

@@ -0,0 +1,56 @@
+<template>
+  <div class="my_input_component">
+    <el-input style="width:100%" :style="customStyle" v-bind="$attrs" v-on="$listeners">
+    </el-input>
+    <span class="placeHolder">
+        <slot name="placeholder"></slot>
+    </span>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {},
+  props: {
+    customStyle:{
+        type:String,
+        default:''
+    }
+  },
+  data() {
+    return {
+    };
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {},
+  methods: {},
+};
+</script>
+<style lang="scss">
+.my_input_component{
+    --height: 50px;
+    position: relative;
+    .el-input{
+        width:100%;
+    }
+    .el-input__inner{
+        border-radius: var(--height);
+        background: rgb(233,232,232);
+        height: var(--height);
+        z-index: 999;
+        opacity: 0.5;
+    }
+    .placeHolder{
+        position: absolute;
+        left: 30px;
+        line-height: var(--height);
+        font-style: normal;
+        white-space: nowrap;
+        color: #4e4f50;
+        z-index: -1;
+    }
+}
+
+</style>

+ 10 - 0
src/utils/permissions.js

@@ -0,0 +1,10 @@
+import Store from '@/store'
+
+export const hasRole = (projectId, roles) => {
+  if (!projectId) {
+    return true
+  }
+  const permissions = Store.getters && Store.getters.permissions
+  const p = permissions[projectId]
+  return p === 0 || roles.indexOf(p) !== -1
+}

+ 33 - 0
src/utils/storage.js

@@ -0,0 +1,33 @@
+import cookie from 'js-cookie'
+export default {
+  setObj(key, value) {
+    localStorage.setItem(key, JSON.stringify(value))
+  },
+  getObj(key) {
+    return JSON.parse(localStorage.getItem(key))
+  },
+  removeObj(key) {
+    localStorage.removeItem(key)
+  },
+  getSession(key) {
+    return JSON.parse(sessionStorage.getItem(key))
+  },
+  setSession(key, value) {
+    sessionStorage.setItem(key, JSON.stringify(value))
+  },
+  setCookie(key, value) {
+    cookie.set(key, value)
+  },
+  getCookie(key) {
+    return cookie.get(key)
+  },
+  setStr(key, value) {
+    localStorage.setItem(key, value)
+  },
+  getStr(key) {
+    return localStorage.getItem(key)
+  },
+  getInt(key) {
+    return parseInt(localStorage.getItem(key))
+  },
+}

+ 71 - 0
src/views/home/components/downLoad/downLoad.vue

@@ -0,0 +1,71 @@
+<template>
+  <div class="main">
+    <div class="title">
+        <div>欢迎使用</div>
+        <div>窍笔撰写辅助工具</div>
+        <div class="downLoad">
+            <el-button round style="width:100%;color:black;font-size:16px;height:50px;font-weight:bold;" @click="submit">点击下载</el-button>
+        </div>
+    </div>
+    
+  </div>
+</template>
+
+<script>
+export default {
+  components: {},
+  props: {},
+  data() {
+    return {
+    };
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {},
+  methods: {
+    submit(){
+        const anchor = document.createElement('a');
+        if ('download' in anchor) {
+            anchor.href = 'https://xsip.cn/api/fileManager/downloadFile?fileId=2409271555';
+            anchor.setAttribute("download", '窍笔');
+            anchor.className = "download-js-link";
+            anchor.innerHTML = "downloading...";
+            anchor.style.display = "none";
+            document.body.appendChild(anchor);
+            setTimeout(function () {
+                anchor.click();
+                document.body.removeChild(anchor);
+            }, 66);
+            return true;
+        }
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.main{
+    width: 100%;
+    height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: space-around;
+    flex-direction: column;
+    .title{
+        width: 350px;
+        max-width: 80%;
+        text-align: center;
+        font-size: 34px;
+        // color: var(--color);
+        color:white;
+        &>div{
+            margin-bottom: 10px;
+            line-height:60px;
+            font-weight: bold;
+        }
+    }
+    .downLoad{
+        margin-top: 30px;
+    }
+}
+</style>

+ 0 - 0
src/views/home/components/downLoad/index.vue


+ 21 - 0
src/views/home/components/functionIntroduction/functionIntroduction.vue

@@ -0,0 +1,21 @@
+<template>
+  <div>功能介绍</div>
+</template>
+
+<script>
+export default {
+  components: {},
+  props: {},
+  data() {
+    return {
+    };
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {},
+  methods: {},
+};
+</script>
+<style lang="scss" scoped>
+</style>

+ 0 - 0
src/views/home/components/functionIntroduction/index.vue


+ 21 - 0
src/views/home/components/softwareSupport/index.vue

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

+ 44 - 0
src/views/home/components/softwareSupport/softwareSupport.vue

@@ -0,0 +1,44 @@
+<template>
+  <div class="softwareSupport" :style="`background-image:url(${require('@/assets/image/background2.png')})`">
+    <div class="content">技术支持:小世数字科技(深圳)有限公司</div>
+    <div class="content">联系方式:lishijie@china-wispro.com</div>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {},
+  props: {},
+  data() {
+    return {
+    };
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {},
+  methods: {},
+};
+</script>
+<style lang="scss" scoped>
+.softwareSupport{
+    width: 100%;
+    height: 100%;
+    background-size: cover;
+    background-position: center;
+    position: relative;
+    display: flex;
+    align-items: center;
+    justify-content: space-around;
+    flex-direction: column;
+    .content{
+        width: 320px;
+        max-width: 80%;
+        background: white;
+        padding: 0 15px;
+        height: 50px;
+        line-height: 50px;
+        border-radius: 50px;
+    }
+}
+</style>

+ 21 - 0
src/views/home/components/version/index.vue

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

+ 21 - 0
src/views/home/components/version/version.vue

@@ -0,0 +1,21 @@
+<template>
+  <div>版本信息</div>
+</template>
+
+<script>
+export default {
+  components: {},
+  props: {},
+  data() {
+    return {
+    };
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {},
+  methods: {},
+};
+</script>
+<style lang="scss" scoped>
+</style>

+ 21 - 0
src/views/home/components/videoDemo/index.vue

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

+ 72 - 0
src/views/home/components/videoDemo/videoDemo.vue

@@ -0,0 +1,72 @@
+<template>
+    <div class="videoDemo" :style="`background-image:url(${require('@/assets/image/background.png')})`">
+        <video v-if="isPlay" ref="videoDom" width="100%" height="100%" controls muted preload="auto" crossorigin="anonymous">
+            <source :src="videoSrc" type="video/mp4">
+            您的浏览器不支持视频标签。
+        </video>
+        <div class="playVideo" v-if="!isPlay" >
+            <div class="button">
+                <el-button class="btn" @click="play">播放视频</el-button>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+  components: {
+  },
+  props: {},
+  data() {
+    return {
+        videoSrc: require('@/assets/media/yanshi.mp4'),
+        isPlay:false,
+    };
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {
+    
+  },
+  methods: {
+    play(){
+        this.$message.warning('敬请期待')
+        return
+        this.isPlay = true
+        this.$nextTick(()=>{
+            console.log(this.$refs.videoDom.play)
+            this.$refs.videoDom.play() 
+        })
+    }
+  },
+};
+</script>
+<style lang="scss" scoped>
+.videoDemo{
+    width: 100%;
+    height: 100%;
+    background-size: cover;
+    background-position: center;
+    position: relative;
+}
+.playVideo{
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    inset: 0;
+    background-color:rgba(238, 228, 228, 0.2);
+}
+.button{
+    width: 80px;
+    height: 50px;
+    position: absolute;
+    inset: 0;
+    margin: auto; 
+    .btn{
+        background-color:rgba(238, 228, 228, 0.2);
+        color: black;
+        font-weight: bold;
+    }
+}
+</style>

+ 102 - 0
src/views/home/index.vue

@@ -0,0 +1,102 @@
+<template>
+  <div class="home" :style="`background-image:url(${require('@/assets/image/login_background.jpg')})`">
+    <div class="logo">
+        <el-image :src="require('@/assets/image/logo3.png')" class="img" fit="contain"></el-image>
+    </div>
+    <div class="content">
+        <div v-for="(component,index) in components" :key="index" style="width:33%">
+            <components :is="component.component"></components>
+        </div>
+    </div>
+    <div class="copyright">
+      copyright©灵智信息服务(深圳)有限公司
+    </div>
+  </div>
+</template>
+
+<script>
+import videoDemo from './components/videoDemo/videoDemo.vue';
+import softwareSupport from './components/softwareSupport/softwareSupport.vue';
+import downLoad from './components/downLoad/downLoad.vue'
+export default {
+  components: {
+    videoDemo,
+    softwareSupport,
+    downLoad
+  },
+  props: {},
+  data() {
+    return {
+        components:[
+            {
+                component:'videoDemo'
+            },
+            {
+                component:'downLoad'
+            },
+            {
+                component:'softwareSupport'
+            },
+        ]
+    };
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {},
+  methods: {},
+};
+</script>
+<style lang="scss" scoped>
+.home{
+  width: 100vw;
+  height: 100vh;
+  background-size: cover;
+  background-position: center;
+  position: relative;
+}
+.home::after{
+  content:'';
+  width: 100%;
+  height: 100%;
+  position: absolute;
+  inset: 0;
+  background: var(--color);
+  opacity: 0.5;
+}
+.logo{
+    position: absolute;
+    top: 0;
+    left: 0;
+    height: 120px;
+    width: fit-content;
+    z-index: 9999;
+    .img{
+        width: 100%;
+        height: 100%;
+    }
+}
+.content{
+    // height: 400px;
+    min-height: 300px;
+    height:fit-content;
+    z-index: 9999;
+    position: absolute;
+    inset: 0;
+    margin: auto;
+    display: flex;
+    align-items: stretch;
+    justify-content: space-between;
+    padding: 0 10px;
+}
+.copyright{
+  position: absolute;
+  right: 0;
+  left: 0;
+  bottom: 35px;
+  margin: auto;
+  text-align: center;
+  color: white;
+  z-index: 9999;
+}
+</style>

+ 115 - 0
src/views/home/index_old.vue

@@ -0,0 +1,115 @@
+<template>
+  <div class="home">
+    <div class="head">
+        <div class="logo">
+            <el-image :src="require('@/assets/image/logo2.png')" class="img" fit="contain"></el-image>
+        </div>
+    </div>
+    <div class="menu">
+        <div v-for="(item,index) in menus" :key="index" :class="['menu_item',item.path==component?'isActive':'']" @click="changeComponent(item)">{{ item.label }}</div>
+    </div>
+    <div class="content">
+        <components :is="component"></components>
+    </div>
+    <div class="copyright">
+      copyright©灵智信息服务(深圳)有限公司
+    </div>
+  </div>
+</template>
+
+<script>
+import versionPage from './components/version/version.vue';
+import functionIntroduction from './components/functionIntroduction/functionIntroduction.vue';
+import videoDemo from './components/videoDemo/videoDemo.vue';
+import softwareSupport from './components/softwareSupport/softwareSupport.vue'
+export default {
+  components: {
+    versionPage,
+    functionIntroduction,
+    videoDemo,
+    softwareSupport
+  },
+  props: {},
+  data() {
+    return {
+        component:'versionPage',
+        menus:[
+            {
+                label:'版本信息',
+                path:'versionPage',
+            },
+            {
+                label:'功能介绍',
+                path:'functionIntroduction',
+            },
+            {
+                label:'视频演示',
+                path:'videoDemo',
+            },
+            {
+                label:'软件支持',
+                path:'softwareSupport',
+            },
+        ]
+    };
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {},
+  methods: {
+    changeComponent(item){
+        this.component = item.path
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.home{
+    // position: relative;
+    height: calc(100vh - 45px);
+    overflow: auto;
+}
+.head{
+    height: 150px;
+    background: var(--color);
+    .img{
+        margin:20px 0 0 20px;
+        height: 70px;
+    }
+}
+.menu{
+    display: flex;
+    justify-content: space-around;
+    margin-top: -20px;
+    .menu_item{
+        cursor: pointer;
+        background: white;
+        border-radius: 10px;
+        width: 196px;
+        line-height: 66px;
+        text-align: center;
+        color: var(--color);
+        font-size: 22px;
+        box-shadow:0 5px 8px rgba(0,0,0,.5);
+    }
+    .isActive{
+        background: var(--color);
+        color:white;
+    }
+}
+.content{
+    padding: 20px;
+    // margin-bottom: 50px;
+}
+.copyright{
+  position: fixed;
+  right: 0;
+  left: 0;
+  bottom: 15px;
+  margin: auto;
+  text-align: center;
+//   color: white;
+  z-index: 9999;
+}
+</style>

+ 31 - 0
src/views/index/index.vue

@@ -0,0 +1,31 @@
+<template>
+  <div id="app">
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+    }
+  },
+  watch:{
+  },
+  mounted() {
+    this.$router.push({path: '/home'})
+  }
+}
+</script>
+<style lang="scss">
+
+  
+</style>
+<style lang="scss" scoped>
+#app{
+    width: 100%;
+    height: 100%;
+    // overflow:hidden;
+    background: white;
+}
+
+</style>

+ 206 - 0
src/views/layout/components/UserBar.vue

@@ -0,0 +1,206 @@
+<template>
+  <div class="admin-user-bar">
+    <el-dropdown class="user panel-item" trigger="click" @command="handleCommand">
+      <div class="user-avatar">
+        <el-avatar :size="30" :src="require('@/assets/user-avatar.jpeg')"></el-avatar>
+        <label>{{ userinfo.name }}</label>
+        <div class="el-icon--right"><i class="el-icon-arrow-down"></i></div>
+      </div>
+      <template slot="dropdown">
+        <el-dropdown-menu>
+          <!-- <el-dropdown-item command="userinfo">个人信息</el-dropdown-item> -->
+          <el-dropdown-item command="changePwd" v-if="$permission('/admin/updatePassword')" >修改密码</el-dropdown-item>
+          <el-dropdown-item divided command="doLogout">退出登录</el-dropdown-item>
+        </el-dropdown-menu>
+      </template>
+    </el-dropdown>
+
+    <el-dialog title="修改密码" :visible.sync="changePwdDialogVisible" width="500px">
+      <el-form :model="changePwdRuleForm" :rules="changePwdRules" ref="changePwdRuleForm" v-if="changePwdDialogVisible">
+        <el-form-item label="旧密码" prop="oldPassword">
+          <el-input v-model="changePwdRuleForm.oldPassword" type="password" placeholder="输入旧密码" />
+        </el-form-item>
+        <el-form-item label="新密码" prop="newPassword">
+          <el-input v-model="changePwdRuleForm.newPassword" type="password" placeholder="输入新密码" />
+        </el-form-item>
+        <el-form-item label="再次输入" prop="repeat">
+          <el-input v-model="changePwdRuleForm.repeat" type="password" placeholder="再次输入" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="changePwdDialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="submitChangePwd" :loading="btnLoading">确 定</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+
+export default {
+  data() {
+    const validateRepeat = (rule, value, callback) => {
+      if (value === '') {
+        callback(new Error('请再次输入新密码'))
+      } else if (value !== this.changePwdRuleForm.newPassword) {
+        callback(new Error("两次输入密码不一致"))
+      } else {
+        callback()
+      }
+    }
+    const isPassword = (rule, value, callback) => {
+      if (value) {
+          //校验特殊字符 ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[`~!#$%^&*()_\-+=<>?:\"{}|,.\/;'\\[\]]).{6,}$
+          let reg = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[`~!#$%^&*()_\-+=<>?:\"{}|,.\/;'\\[\]·!@¥……()——【】、:;‘’“”,。/《》? ]).{6,}$/
+          let re = new RegExp(reg)
+          if (re.test(value)) {
+            callback()
+          } else {
+            callback(new Error('密码必须包含大小写字母、数字、特殊字符且长度至少为六位的组合'))
+          }
+        } else {
+          callback(new Error('请输入新密码'))
+        }
+      };
+    return {
+      changePwdDialogVisible: false,
+      btnLoading: false,
+      changePwdRuleForm: {
+        oldPassword: '',
+        newPassword: '',
+        repeat: '',
+      },
+      changePwdRules: {
+        oldPassword: {
+          required: true,
+          message: '请输入旧密码'
+        },
+        newPassword: [{
+          required: true,
+          validator: isPassword,
+          trigger: 'blur',
+        }],
+        repeat: [{ validator: validateRepeat, trigger: 'blur', required: true }]
+      }
+    }
+  },
+  computed: {
+    userinfo() {
+      return this.$store.state.admin.userinfo
+    }
+  },
+  mounted() {
+  },
+  methods: {
+    resetChangePwdRuleForm() {
+      this.changePwdRuleForm = {
+        oldPassword: '',
+        newPassword: '',
+        repeat: '',
+      }
+    },
+    handleCommand(command) {
+      switch (command) {
+        case 'doLogout':
+          this.$api.adminLogout().then(response => {
+            this.$router.push({ path: '/admin/login' })
+          })
+          break;
+        case 'changePwd':
+          this.resetChangePwdRuleForm()
+          this.changePwdDialogVisible = true
+          break;
+        case 'userinfo':
+          break;
+      }
+    },
+    submitChangePwd() {
+      this.$refs.changePwdRuleForm.validate((valid) => {
+        if (valid) {
+          this.btnLoading = true
+          this.$api.ChangePassword(this.changePwdRuleForm).then(response => {
+            this.$message.success('修改成功')
+            this.changePwdDialogVisible = false
+            this.btnLoading = false
+          }).catch(err => {
+            this.btnLoading = false
+          })
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+.admin-user-bar {
+  display: flex;
+  align-items: center;
+  height: 100%;
+
+  .panel-item:hover {
+    background: rgba(255, 255, 255, 0.1) !important;
+  }
+
+  .user label {
+    color: #fff;
+  }
+
+  .panel-item {
+    padding: 0 10px;
+    cursor: pointer;
+    height: 100%;
+    display: flex;
+    align-items: center;
+  }
+
+  .panel-item i {
+    font-size: 16px;
+  }
+
+  .panel-item:hover {
+    background: rgba(0, 0, 0, 0.1);
+  }
+
+  .user-avatar {
+    height: 49px;
+    display: flex;
+    align-items: center;
+  }
+
+  .user-avatar label {
+    display: inline-block;
+    margin-left: 5px;
+    font-size: 12px;
+    cursor: pointer;
+    color: #383838;
+  }
+
+  .bell-bar {
+    margin-right: 10px;
+    cursor: pointer;
+    padding: 10px;
+    border-radius: 5px;
+    position: relative;
+  }
+  .bell-bar:hover {
+    background-color: rgba(153, 148, 148, 0.35);
+  }
+  .bell-bar .el-icon-bell {
+    font-size: 20px;
+    z-index: 20;
+  }
+  .bell-bar .current-num {
+    position: absolute;
+    background: red;
+    border-radius: 50%;
+    width: 20px;
+    height: 20px;
+    font-size: 13px;
+    text-align: center;
+    top: 20px;
+    left: 20px;
+  }
+}
+</style>

+ 44 - 0
src/views/layout/index.vue

@@ -0,0 +1,44 @@
+<template>
+  <div id="admin">
+    <section class="wrapper">
+      <router-view></router-view>
+      <!-- <el-container>
+        <el-container>
+          <el-header></el-header>
+          <el-main class="admin-main-box">
+            <router-view></router-view>
+          </el-main>
+        </el-container>
+      </el-container> -->
+    </section>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {
+  },
+    mixins: [],
+  data() {
+    return {
+    }
+  },
+  watch: {
+  },
+  computed: {
+  },
+  created(){
+  },
+  mounted() {
+  },
+  methods: {
+
+  }
+}
+</script>
+<style lang="scss">
+
+</style>
+<style lang="scss">
+
+</style>

+ 25 - 0
src/views/layout/mixins/index.js

@@ -0,0 +1,25 @@
+import Config from '@/config'
+import Store from '@/store'
+
+export const webSocket = {
+  methods: {
+    connectWebSocket(userId) {
+      // let webSocket = new WebSocket(`ws://139.224.24.90:8871/permission/api/ws/` + userId)
+      let webSocket = new WebSocket(`ws://139.224.24.90:8880/permission/api/ws/` + userId)
+      Store.commit('SET_WEB_SOCKET', webSocket)
+      webSocket.onopen = () => {
+        console.log('WebSocket连接成功')
+      }
+      // webSocket.onmessage = async (e) => {
+      //   console.log(e)
+      // }
+      webSocket.onerror = () => {
+        console.log('WebSocket连接失败')
+      }
+      webSocket.onclose = () => {
+        console.log('WebSocket连接关闭')
+      }
+    }
+  }
+}
+

+ 110 - 0
src/views/login/compoments/resePassword.vue

@@ -0,0 +1,110 @@
+<template>
+  <div>
+    <el-dialog
+      title="重置密码"
+      :visible.sync="visible"
+      width="500px"
+      :before-close="close"
+      :close-on-click-modal="false">
+
+      <el-form :model="form" :rules="rules" ref="ruleForm" class="demo-ruleForm">
+        <el-form-item label="账号" prop="personnelUserName">
+          <el-input v-model="form.personnelUserName" placeholder="请输入账号"></el-input>
+        </el-form-item>
+        <el-form-item label="邮箱" prop="personnelEmail">
+          <el-input v-model="form.personnelEmail" placeholder="请输入账号绑定的邮箱"></el-input>
+        </el-form-item>
+      </el-form>
+      
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="close">取 消</el-button>
+        <el-button type="primary" @click="sure">确 定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    const errorPersonnelEmail = (rule, value, callback) => {
+      if (rule.errorMessage) {
+        callback(new Error(rule.errorMessage))
+      } else {
+        if (!value) {
+          callback(new Error('请输入账号绑定的邮箱'))
+        } else {
+          let reg = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9_\.\-])+\.)+([a-zA-Z0-9]{2,4})+$/
+          let re = new RegExp(reg)
+          if (re.test(value)) {
+            callback()
+          } else {
+            callback(new Error('请输入正确的邮箱格式'))
+          }
+        }
+      }
+    }
+    const errorPersonnelUserName = (rule, value, callback) => {
+      if (rule.errorMessage) {
+        callback(new Error(rule.errorMessage))
+      } else {
+        if (!value) {
+          callback(new Error('请输入账号'))
+        } else {
+          callback()
+        }
+      }
+    }
+    return {
+      form: {},
+      visible: false,
+      rules: {
+        personnelUserName: [{ required: true,  validator:errorPersonnelUserName, trigger: 'blur' },],
+        personnelEmail: [
+          { required: true, validator:errorPersonnelEmail, trigger: "blur" },
+        ]
+      },
+    }
+  },
+  mounted() {
+
+  },
+  methods: {
+    
+    open() {
+      this.visible = true
+    },
+    sure() {
+      this.$refs.ruleForm.validate((valid) => {
+        if (valid) {
+          this.$api.reSetPasswordBeforeLogin(this.form).then(res => {
+            if (res.code == 200) {
+              this.$message.success('密码重置成功,请您到邮箱中查看新密码')
+              this.close()
+            }
+          }).catch(error => {
+            if (error.message.indexOf('账号') != -1) {
+              var personnel = 'personnelUserName'
+            }else if (error.message.indexOf('邮箱')!=-1) {
+              var personnel = 'personnelEmail'
+            }
+            this.rules[personnel][0].errorMessage = error.message
+            this.$refs.ruleForm.validateField(personnel)
+            this.rules[personnel][0].errorMessage = ''
+          })
+        } else {
+          return false;
+        }
+      });
+    },
+    close() {
+      this.visible = false
+      this.$refs.ruleForm.resetFields()
+    },
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 133 - 0
src/views/login/index.vue

@@ -0,0 +1,133 @@
+<template>
+  <div class="login" :style="`background-image:url(${require('@/assets/image/login_background.jpg')})`">
+    <div class="content">
+      <div class="logo">
+        <el-image :src="require('@/assets/image/logo.jpg')" class="img" fit="contain"></el-image>
+      </div>
+      <div class="body">
+        <div class="title">
+          <div>欢迎使用</div>
+          <div>窍笔撰写辅助工具</div>
+        </div>
+        <div class="input">
+          <div class="username">
+            <myInput>
+              <span slot="placeholder" style="line-height:50px" ><span class="iconfont icon-yonghuming"></span> 账号</span>
+            </myInput>
+          </div>
+          <div class="password">
+            <myInput>
+              <span slot="placeholder" style="line-height:50px" ><span class="iconfont icon-mima"></span> 密码</span>
+            </myInput>
+          </div>
+        </div>
+        <div class="forget">
+          <span class="forget_btn" @click="forget">忘记密码了?</span>
+        </div>
+        <div class="btn">
+          <el-button round style="width:100%;background:var(--color);color:white;height:50px;" @click="submit">登录</el-button>
+        </div>
+      </div>
+    </div>
+    <div class="copyright">
+      copyright©灵智信息服务(深圳)有限公司
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {},
+  props: {},
+  data() {
+    return {
+    };
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {},
+  methods: {
+    forget(){},
+    submit(){
+      this.$router.push(
+        {
+          path:'/home',
+        }
+      )
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.login{
+  width: 100vw;
+  height: 100vh;
+  background-size: cover;
+  background-position: center;
+  position: relative;
+}
+.login::after{
+  content:'';
+  width: 100%;
+  height: 100%;
+  position: absolute;
+  inset: 0;
+  background: var(--color);
+  opacity: 0.5;
+}
+
+.content{
+  width: 800px;
+  height: fit-content;
+  background: white;
+  position: absolute;
+  inset: 0;
+  margin: auto;
+  z-index: 999;
+  padding: 20px;
+  .img{
+    height: 50px;
+  }
+}
+.body{
+  width:400px;
+  padding: 20px 0 35px 0;
+  margin: auto;
+  .title{
+    text-align: center;
+    font-size: 34px;
+    color: var(--color);
+    &>div{
+      margin-bottom: 10px;
+    }
+  }
+  .input{
+    margin:20px 0;
+    &>div{
+      margin-bottom: 10px;
+    }
+  }
+}
+.forget{
+  text-align: center;
+  font-size: 14px;
+  .forget_btn{
+    color: var(--color);
+    cursor: pointer;
+  }
+}
+.btn{
+  margin-top:20px;
+}
+.copyright{
+  position: absolute;
+  right: 0;
+  left: 0;
+  bottom: 35px;
+  margin: auto;
+  text-align: center;
+  color: white;
+  z-index: 9999;
+}
+</style>

+ 900 - 0
src/views/user/index.vue

@@ -0,0 +1,900 @@
+<template>
+	<div class="admin-user">
+		<el-form :inline="true">
+			<el-form-item v-if="$permission('/admin/user/check')">
+				<el-input
+					v-model="queryParams.name"
+					size="small"
+					placeholder="请输入"
+				></el-input>
+			</el-form-item>
+			<el-form-item class="tenant" v-if="userinfo.rList?(userinfo.rList.filter(item=>item.roleId==1))[0]:''">
+        		<el-select v-model="queryParams.tenant"  @change="getList2" clearable placeholder="根据租户查询">
+					<el-option
+						v-for="item in tenantList"
+						:key="item.id"
+						:label="item.name"
+						:value="item.id">
+					</el-option>
+				</el-select>
+      </el-form-item>
+			
+			<!-- <el-form-item label="用户名">
+        <el-input v-model="queryParams.name" size="small" placeholder="请输入用户名"></el-input>
+      </el-form-item> -->
+			<el-form-item>
+				<el-button type="" size="small" @click="getList2" v-if="$permission('/admin/user/check')">查询</el-button>
+				<el-button type="primary" size="small" @click="handleAdd()" v-if="$permission('/admin/user/add')">新增</el-button
+				>
+			</el-form-item>
+		</el-form>
+		<el-table
+			v-loading="loading"
+			:data="tableData"
+			border
+			header-row-class-name="custom-table-header"
+		>
+			<el-table-column
+				type="index"
+				label="#"
+				width="55"
+				align="center"
+			>
+			<template slot-scope="scope">
+          <span>{{ (scope.$index + 1) + ((queryParams.current - 1) * queryParams.size) }}</span>
+        </template>
+			</el-table-column>
+			<el-table-column
+				prop="name"
+				label="姓名"
+				align="center"
+				show-overflow-tooltip
+			></el-table-column>
+			<el-table-column
+				prop="username"
+				label="账号"
+				align="center"
+				show-overflow-tooltip
+			></el-table-column>
+			<el-table-column label="性别" align="center" show-overflow-tooltip>
+				<template slot-scope="scope">
+					<span>{{ genderObj[scope.row.gender] }}</span>
+				</template>
+			</el-table-column>
+			<el-table-column
+				prop="email"
+				label="邮箱"
+				align="center"
+				show-overflow-tooltip
+			></el-table-column>
+			<el-table-column
+				prop="mobile"
+				label="联系方式"
+				align="center"
+				show-overflow-tooltip
+			></el-table-column>
+			<el-table-column
+				prop="tenantName"
+				label="所属租户"
+				align="center"
+				show-overflow-tooltip
+			></el-table-column>
+			<el-table-column label="是否启用" align="center" show-overflow-tooltip>
+				<template slot-scope="scope">
+					<span v-if="scope.row.state == 0">否</span>
+					<span v-if="scope.row.state == 1">是</span>
+				</template>
+			</el-table-column>
+			<el-table-column
+				prop="remark"
+				label="备注"
+				align="center"
+				show-overflow-tooltip
+			></el-table-column>
+			<el-table-column label="操作" align="center" width="150">
+				<template slot-scope="scope">
+					<el-dropdown split-button type="primary" size="small" >
+						<p @click="handleEdit(scope.row)" v-if="$permission('/admin/user/modify')">编辑</p>
+						<p v-else :disabled="true">编辑</p>
+						<el-dropdown-menu slot="dropdown" class="text-align_center">
+							<!-- <el-dropdown-item @click.native="handleDetails(scope.row)" divided  v-if="$permission('/admin/user/detail')">人员详情</el-dropdown-item> -->
+							<el-dropdown-item @click.native="handleReset(scope.row)" v-if="$permission('/admin/user/reset')">重置密码</el-dropdown-item>
+							<el-dropdown-item class="color-red" @click.native="handleDelete(scope.row)" divided  v-if="$permission('/admin/user/delete')">删除</el-dropdown-item>
+						</el-dropdown-menu>
+					</el-dropdown>
+				</template>
+			</el-table-column>
+		</el-table>
+		<div class="pagination">
+			<el-pagination
+				:current-page.sync="queryParams.current"
+				:page-size="queryParams.size"
+				:total="total"
+				@current-change="handleCurrentChange"
+				layout="total, prev, pager, next, jumper"
+				background
+			></el-pagination>
+		</div>
+		<el-dialog
+			:title="title"
+			:visible.sync="visible"
+			width="700px"
+			:before-close="close"
+		>
+			<el-form
+				v-if="visible"
+				:model="ruleForm"
+				:rules="rules"
+				ref="ruleForm"
+				label-width="100px"
+				label-position="left"
+			>
+				<el-row :gutter="24">
+					<el-col :span="12">
+						<el-form-item label="姓名" prop="name">
+							<el-input
+								v-model="ruleForm.name"
+								placeholder="请输入姓名"
+							></el-input>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="性别" prop="gender">
+							<el-select
+								v-model="ruleForm.gender"
+								class="width_100"
+								placeholder="请选择"
+							>
+								<el-option
+									v-for="(item, key) in genderObj" :key="key"
+									:label="item"
+									:value="parseInt(key)"
+								></el-option>
+							</el-select>
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-row :gutter="24">
+					<el-col :span="12">
+						<el-form-item label="邮箱" prop="email">
+							<el-input
+								v-model="ruleForm.email"
+								placeholder="请输入邮箱"
+							></el-input>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="联系方式" prop="mobile">
+							<el-input
+								v-model="ruleForm.mobile"
+								placeholder="请输入联系方式"
+							></el-input>
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-row :gutter="24">
+					<el-col :span="12">
+						<el-form-item label="QQ号" prop="qqNumber">
+							<el-input
+								type="text"
+								v-model="ruleForm.qqNumber"
+								placeholder="请输入QQ号"
+								@input="change($event)"
+							></el-input>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="微信号" prop="wechat">
+							<el-input
+								v-model="ruleForm.wechat"
+								placeholder="请输入微信号"
+							></el-input>
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-row :gutter="24">
+					<el-col :span="12">
+						<el-form-item label="钉钉号" prop="nail">
+							<el-input
+								v-model="ruleForm.nail"
+								placeholder="请输入钉钉号"
+							></el-input>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="所属租户" prop="tenant">
+							<!-- <el-tooltip
+								class="item"
+								effect="dark"
+								:disabled="!ruleForm.tenantName"
+								:content="ruleForm.tenantName"
+								placement="top-start"
+							>
+								<el-input
+									v-model="ruleForm.tenantName"
+									placeholder="请输入所属租户"
+									:readonly="true"
+								></el-input>
+							
+							</el-tooltip> -->
+								<el-select v-model="ruleForm.tenant" :disabled="(userinfo.rList?!(userinfo.rList.filter(item=>item.roleId==1))[0]:'')||disabled" placeholder="请选择">
+										<el-option
+										v-for="item in tenantList"
+										:key="item.id"
+										:label="item.name"
+										:value="item.id">
+										</el-option>
+									</el-select>
+						</el-form-item>
+					</el-col>
+				</el-row>
+
+				<el-row :gutter="24">
+					<el-col :span="24">
+						<el-form-item label="职位[部门]" prop="nail">
+							<template>
+								<el-col :span="11" style="padding-left: 0">
+									<el-form-item label-width="0" prop="position">
+										<el-tooltip
+											class="item"
+											effect="dark"
+											:disabled="!labelVal"
+											:content="labelVal"
+											placement="top-start"
+										>
+											<el-cascader
+												ref="deptIdCascader"
+												v-model="positionAndDepartment.department"
+												:options="departmentList"
+												:show-all-levels="false"
+												:props="{
+													checkStrictly: true,
+													value: 'id',
+													label: 'name',
+												}"
+												clearable
+												@change="handleChange"
+												placeholder="请选择部门"
+											>
+											</el-cascader>
+										</el-tooltip>
+									</el-form-item>
+								</el-col>
+
+								<el-col :span="11" style="padding-left: 0">
+									<el-form-item
+										label-width="0"
+										label-height="82"
+										label-line-height="82px"
+										prop="position"
+									>
+										<el-select
+											v-model="positionAndDepartment.position"
+											filterable
+											placeholder="请选择职位"
+										>
+											<el-option
+												v-for="item in positionList"
+												:key="item.name"
+												:label="item.position"
+												:value="item.id"
+											></el-option>
+										</el-select>
+									</el-form-item>
+								</el-col>
+								<el-col :span="2">
+									<el-button
+										type="primary"
+										size="mini"
+										@click="showInputLabel"
+										circle
+										icon="el-icon-plus"
+									></el-button>
+								</el-col>
+								<el-col :span="24" style="padding-left: 0; margin: 10px 0 0 0">
+									<template>
+										<div
+											style="
+												width: 100%;
+												height: 75px;
+												border: 1px solid #c0c0c0;
+												border-radius: 4px;
+												overflow: auto;
+											"
+										>
+											<el-tag
+												v-for="(tag, index) in ruleForm.positions"
+												:key="index"
+												closable
+												:disable-transitions="false"
+												@close="handleClose(index)"
+											>
+												<span
+													>{{ tag.positionName }}<span v-if="tag.departmentName">[{{
+														tag.departmentName
+													}}]</span></span
+												>
+											</el-tag>
+										</div>
+									</template>
+								</el-col>
+							</template>
+						</el-form-item>
+					</el-col>
+				</el-row>
+
+				<el-row :gutter="24">
+					<el-col :span="12">
+						<el-form-item label="所属用户组" prop="group">
+							<el-select
+								v-model="ruleForm.group"
+								multiple
+								collapse-tags
+								placeholder="请选择用户组"
+							>
+								<el-option
+									v-for="item in groupList"
+									:key="item.id"
+									:label="item.name"
+									:value="item.id"
+								>
+								</el-option>
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="所属角色" prop="role" class="role">
+							<el-select
+								v-model="ruleForm.role"
+								multiple
+								collapse-tags	
+								placeholder="请选择所属角色"
+							>
+								<el-option
+									v-for="item in roleList"
+									:key="item.id"
+									:label="item.name"
+									:value="item.id"
+									:disabled="item.disabled"
+								>
+								</el-option>
+							</el-select>
+						</el-form-item>
+					</el-col>
+				</el-row>
+
+				<el-row :gutter="24">
+					<el-col :span="12">
+						<el-form-item label="账号" prop="username">
+							<el-input
+								v-model="ruleForm.username"
+								placeholder="请输入账号"
+							></el-input>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item v-if="pswdshow" label="密码" prop="password">
+							<el-input
+								v-model="ruleForm.password"
+								placeholder="请输入密码"
+							></el-input>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="是否启用" prop="state">
+							<el-switch
+								:active-value="1"
+								:inactive-value="0"
+								v-model="ruleForm.state"
+								active-color="#13ce66"
+								inactive-color="#ff4949"
+							>
+							</el-switch>
+							<!-- <el-input v-model="ruleForm.state" placeholder="请输入状态" type="textarea"></el-input> -->
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-form-item label="备注" prop="remark">
+					<el-input
+						v-model="ruleForm.remark"
+						placeholder="请输入备注"
+						type="textarea"
+						maxlength="100"
+						show-word-limit
+					></el-input>
+				</el-form-item>
+			</el-form>
+			<div slot="footer" class="dialog-footer">
+				<el-button @click="close">取 消</el-button>
+				<el-button type="primary" @click="submit" :loading="btnLoading"
+					>确 定</el-button
+				>
+			</div>
+		</el-dialog>
+
+		<el-dialog
+			:title="title"
+			:visible.sync="showvisible"
+			width="700px"
+			class="my-dialog-name"
+			contentStyle="width:400px;"
+			:before-close="close"
+			v-if="ruleForm.apply != null"
+		>
+			<el-form
+				label-position="left"
+				class="demo-table-expand"
+				label-width="80px"
+			>
+				<el-form-item label="账号 :" class="marginB">
+					<span>{{ ruleForm.apply.username }}</span>
+				</el-form-item>
+				<el-form-item label="姓名 :" class="marginB">
+					<span>{{ ruleForm.apply.remark }}</span>
+				</el-form-item>
+				<el-form-item label="性别 :" class="marginB">
+					<span>{{ ruleForm.apply.gender === 1 ? "男" : "女" }}</span>
+				</el-form-item>
+				<el-form-item label="邮箱 :" class="marginB">
+					<span>{{ ruleForm.apply.email }}</span>
+				</el-form-item>
+				<el-form-item label="联系方式 :" class="marginB">
+					<span>{{ ruleForm.apply.mobile }}</span>
+				</el-form-item>
+				<el-form-item label="QQ号 :" class="marginB">
+					<span>{{ ruleForm.apply.qqNumber }}</span>
+				</el-form-item>
+				<el-form-item label="微信号 :" class="marginB">
+					<span>{{ ruleForm.apply.mobile }}</span>
+				</el-form-item>
+				<el-form-item label="钉钉号 :" class="marginB">
+					<span>{{ ruleForm.apply.nail }}</span>
+				</el-form-item>
+        <el-form-item label="所属租户 :" class="marginB">
+					<span>{{ ruleForm.apply.tenantName }}</span>
+				</el-form-item>
+        <el-form-item label="用户组 :" class="marginB">
+					<span v-for="item in ruleForm.apply.groupList">{{ item.name }}</span>
+				</el-form-item>
+        <el-form-item label="所属角色 :" class="marginB">
+					<span v-for="item in ruleForm.apply.roleList">{{ item.name }}</span>
+				</el-form-item>
+        <!-- <el-form-item label="账号 :" class="marginB">
+					<span>{{ ruleForm.apply.nail }}</span>
+				</el-form-item> -->
+				<el-form-item label="是否启用 :" class="marginB">
+					<span>{{ ruleForm.apply.state === 1 ? "已启用" : "未启用" }}</span>
+				</el-form-item>
+				<el-form-item label="备注 :" class="marginB">
+					<span>{{ ruleForm.apply.remark }}</span>
+				</el-form-item>
+			</el-form>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+	import Treeselect from "@riophae/vue-treeselect"
+	import "@riophae/vue-treeselect/dist/vue-treeselect.css"
+	export default {
+		components: {
+			Treeselect
+		},
+		
+		data() {
+      const isMobile = (rule, value, callback) => {
+        if (value) {
+          var reg = /(^((\+86)|(86))?(1[3-9])\d{9}$)|(^(0\d{2,3})-?(\d{7,8})$)/
+          var re = new RegExp(reg)
+          if (re.test(value)) {
+            callback()
+          } else {
+            callback(new Error('输入的手机号码格式不正确,请重新输入'))
+          }
+        } else {
+          callback()
+        }
+      };
+      const isPassword = (rule, value, callback) => {
+        if (value) {
+          let reg = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[`~!#$%^&*()_\-+=<>?:\"{}|,.\/;'\\[\]·!@¥……()——【】、:;‘’“”,。/《》? ]).{6,}$/
+          let re = new RegExp(reg)
+          if (re.test(value)) {
+            callback()
+          } else {
+            callback(new Error('密码必须包含大小写字母、数字、特殊字符且长度至少为六位的组合'))
+          }
+        } else {
+          callback(new Error('请输入密码'))
+        }
+      };
+			return {
+				disabled:false,
+				pswdshow: false,
+				showvisible: false,
+				visible: false,
+				loading: false,
+				btnLoading: false,
+				total: 0,
+				tableData: [],
+				tenantList:[],
+				title: "",
+				roleList: [
+					{
+						value: "选项1",
+						label: "黄金糕",
+					},
+					{
+						value: "选项2",
+						label: "双皮奶",
+					},
+					{
+						value: "选项3",
+						label: "蚵仔煎",
+					},
+					{
+						value: "选项4",
+						label: "龙须面",
+					},
+					{
+						value: "选项5",
+						label: "北京烤鸭",
+					},
+				],
+				queryParams: {
+					size: 10,
+					current: 1,
+					// username: '',
+          departmentIds: [],
+          positionIds:[],
+					name: "",
+					tenant:''
+				},
+				labelVal: "",
+				departmentList: [],
+				positionList: [],
+				groupList: [],
+				roleList: [],
+				genderObj: {
+					0: "女",
+					1: "男",
+				},
+				positionAndDepartment: {},
+				// departmentList: [],
+				ruleForm: {},
+				rules: {
+					name: [{ required: true, message: "请输入姓名", trigger: "blur" }],
+					username: [{ required: true, message: "请输入账号", trigger: "blur" }],
+					password: [{ required: true, validator:isPassword, trigger: "blur" }],
+					mobile: [
+						{ required: false, validator:isMobile, trigger: "blur" },
+						// {
+						// 	pattern:
+						// 		/(^((\+86)|(86))?(1[3-9])\d{9}$)|(^(0\d{2,3})-?(\d{7,8})$)/,
+						// 	message: "输入的手机号码格式不正确,请重新输入",
+						// 	trigger: "blur",
+						// },
+					],
+					email: [
+						{ required: true, message: "请输入邮箱", trigger: "blur" },
+						{
+							pattern:
+								/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9_\.\-])+\.)+([a-zA-Z0-9]{2,4})+$/,
+							message: "请输入正确的邮箱格式",
+							trigger: "blur",
+						},
+					],
+					sex: [{ required: true, message: "请选择性别", trigger: "change" }],
+					// position: [{ required: true, message: '请选择职位', trigger: 'change' },],
+					// department: [{ required: true, message: '请选择部门', trigger: 'change' },],
+					state: [{ required: true, message: "请选择", trigger: "change" }],
+					tenant:[{ required: true, message: "请选择", trigger: "change" }],
+				},
+			};
+		},
+		watch: {
+			"positionAndDepartment.department"() {
+				if (this.$refs.deptIdCascader) {
+					this.$refs.deptIdCascader.dropDownVisible = false;
+				}
+			},
+			"ruleForm.email"(val) {
+				// console.log(val)
+				if (val.indexOf("@qq.com") != -1) {
+					var index = val.indexOf("@qq.com");
+					var str = val.substring(0, index);
+					this.ruleForm.qqNumber = str;
+				} else if (val.indexOf("@qq.com") == -1) {
+				}
+			},
+		},
+		computed: {
+			userinfo() {
+				
+				return this.$store.state.admin.userinfo;
+			},
+		},
+		mounted() {
+			this.getList();
+			this.getDepartment();
+			this.getPositionList();
+			this.getGroupList();
+			this.getRoleList();
+			this.getTenantList()
+		},
+		methods: {
+			 //根据条件查询
+			 getList2(){
+				this.queryParams.current=1
+				this.getList()
+			},
+			change(e) {
+				this.$forceUpdate();
+			},
+			// getqqNumber(val){
+			//   if(val.indexOf('@qq.com')){
+			//     var index = val.indexOf('@qq.com')
+			//     var str = val.substring(0,index)
+			//     this.ruleForm.qqNumber=str
+			//     console.log(this.ruleForm.qqNumber,str)
+			//   }else{
+			//     this.ruleForm.qqNumber=''
+			//   }
+			// },
+			handleClose(index) {
+				this.ruleForm.positions.splice(index, 1);
+			},
+			handleChange(val) {
+				// console.log(val)
+				let res = this.getVal(val, this.departmentList, []);
+				this.labelVal = res.join("/");
+			},
+			getVal(data, options, arr) {
+				options.forEach((e) => {
+					if(data){
+						data.forEach((i) => {
+						if (i == e.id) {
+							arr.push(e.name || e.position);
+							return;
+						} else {
+							if (e.children) {
+								this.getVal([i], e.children, arr);
+							} else {
+								return;
+							}
+						}
+					});
+					}
+					
+				});
+				return arr;
+			},
+			normalizer(node) {
+				if (node.children && !node.children.length) {
+					delete node.children;
+				}
+				return {
+					id: node.id,
+					label: node.name,
+					children: node.children,
+				};
+			},
+			handleAdd() {
+				this.disabled=false
+				this.title = "新增人员";
+				this.pswdshow = true;
+				this.visible = true;
+				this.ruleForm = {
+					tenant:this.userinfo.tenantId,
+					gender: 0,
+					state: 1,
+					positions: [],
+					email:''
+				};
+			},
+			handleEdit(row) {
+				this.disabled=true
+				this.title = "编辑人员";
+				this.pswdshow = false;
+				this.visible = true;
+				// this.ruleForm = { ...row };
+				this.ruleForm =JSON.parse(JSON.stringify(row));
+			},
+			handleDetails(row) {
+				this.title = "人员详情";
+				this.showvisible = true;
+				this.ruleForm.apply = row;
+			},
+			close() {
+				this.positionAndDepartment = {};
+				this.pswdshow = false;
+				this.visible = false;
+				this.showvisible = false;
+			},
+			getDepartment() {
+				this.$api.getAllDepartmentList().then((response) => {
+					this.departmentList = response.data;
+				});
+			},
+			getPositionList() {
+				this.$api.getAllPositionList().then((response) => {
+					this.positionList = response.data;
+				});
+			},
+			getGroupList() {
+				this.$api.getAllUserGroupList().then((response) => {
+					this.groupList = response.data;
+				});
+			},
+			getTenantList(){
+				this.$api.getAllTenantList().then(response => {
+						this.tenantList = response.data
+					})
+			},
+			getRoleList() {
+        this.$api.getAllRoleList().then((response) => {
+          this.roleList = response.data;
+          var a = this.userinfo.rList.findIndex((item) => {
+              return item.roleId == 1;
+              });
+              if(a == -1){
+                var b = this.roleList.findIndex(i=>{
+                  return i.id == 1
+                })
+                if(b !=-1){
+                  this.roleList[b].disabled=true
+                }
+                
+              }else{
+                this.roleList[0].disabled=false
+              }
+        });
+      },
+			showInputLabel() {
+				// console.log(this.positionAndDepartment.hasOwnProperty('department'))
+				if(this.positionAndDepartment.hasOwnProperty('department')==true){
+					var departmentName = this.getVal(
+					[
+						this.positionAndDepartment.department[
+							this.positionAndDepartment.department.length - 1
+						],
+					],
+					this.departmentList,
+					[]
+				);
+				}else{
+					this.positionAndDepartment.department=[''],
+					 departmentName=['']
+				}
+				
+				var positionName = this.getVal(
+					[this.positionAndDepartment.position],
+					this.positionList,
+					[]
+				);
+				this.ruleForm.positions.push({
+					position: this.positionAndDepartment.position,
+					positionName: positionName[0],
+					department:
+						this.positionAndDepartment.department[
+							this.positionAndDepartment.department.length - 1
+						],
+					departmentName: departmentName[departmentName.length - 1],
+				});
+				
+				this.positionAndDepartment = {};
+				this.labelVal = "";
+			},
+			getList() {
+				this.loading = true;
+				this.$api
+					.getPersonnelList(this.queryParams)
+					.then((response) => {
+            			this.tableData = response.data;
+						this.total = response.pageColumn.total;
+						this.loading = false;
+					})
+					.catch((error) => {
+						this.loading = false;
+					});
+			},
+			handleCurrentChange(val) {
+				this.queryParams.current = val;
+				this.getList();
+			},
+			submit() {
+				this.$refs.ruleForm.validate((valid) => {
+					if (valid) {
+						this.btnLoading = true;
+						if (this.ruleForm.id) {
+							this.$api
+								.editPersonnel(this.ruleForm)
+								.then((response) => {
+									this.$message.success("编辑成功");
+									this.btnLoading = false;
+									this.getList();
+									this.close();
+								})
+								.catch((error) => {
+									this.btnLoading = false;
+								});
+						} else {
+							// this.ruleForm.tenant = this.userinfo.tenantId;
+							this.$api
+								.addPersonnel(this.ruleForm)
+								.then((response) => {
+									if(response.code == 200){
+										this.$message.success("新增成功");
+									}else if(response.code == 0){
+										this.$message.error("新增失败")
+									}
+									// console.log(1212)
+									this.btnLoading = false;
+									this.getList();
+									this.close();
+								})
+								.catch((error) => {
+									this.btnLoading = false;
+								});
+						}
+					} else {
+						// console.log("error submit!!");
+						return false;
+					}
+				});
+			},
+			handleReset(row) {
+				this.$confirm("确认将用户密码重置吗?", "提示", {
+					confirmButtonText: "确定",
+					cancelButtonText: "取消",
+					type: "warning",
+				}).then(() => {
+					this.loading = true;
+					this.$api
+						.ResetPassword({ userId: row.id })
+						.then((response) => {
+							this.$message.success("重置成功");
+							this.loading = false;
+							this.getList();
+						})
+						.catch((error) => {
+							this.loading = false;
+						});
+				});
+			},
+			handleDelete(row) {
+				this.$confirm("确认删除本条数据吗?", "提示", {
+					confirmButtonText: "确定",
+					cancelButtonText: "取消",
+					type: "warning",
+				}).then(() => {
+					this.loading = true;
+					this.$api
+						.deletePersonnel({ id: row.id })
+						.then((response) => {
+							this.$message.success("删除成功");
+							this.loading = false;
+							this.getList();
+						})
+						.catch((error) => {
+							this.loading = false;
+						});
+				});
+			},
+		},
+	};
+</script>
+<style>
+	
+</style>
+<style lang="scss" scoped>
+	.el-tag + .el-tag {
+		margin-left: 10px;
+	}
+	.admin-user {
+	}
+	.marginB {
+		margin-bottom: 0;
+	}
+	
+</style>

+ 122 - 0
vue.config.js

@@ -0,0 +1,122 @@
+const path = require('path')
+const CompressionPlugin = require("compression-webpack-plugin");
+
+function resolve(dir) {
+  return path.join(__dirname, dir)
+}
+module.exports = {
+  publicPath: process.env.NODE_ENV === 'production' ? '/' : '/',
+  lintOnSave: false,
+  productionSourceMap: false,
+  assetsDir: 'assets',
+  // filenameHashing: false,
+  // configureWebpack: () => {
+  //   if (process.env.NODE_ENV === 'production') {
+  //     return {
+  //       plugins: [
+  //         new CompressionPlugin({
+  //           test: /\.js$|\.html$|\.css$|\.jpg$|\.jpeg$|\.png/,
+  //           threshold: 10240,
+  //           deleteOriginalAssets: false
+  //         })
+  //       ]
+  //     }
+  //   }
+  // },
+  chainWebpack: config => {
+    config.plugin('html')
+      .tap(args => {
+        args[0].title = '窍笔'
+        // args[0].inlineSource = '(\.css|\.js$)'
+        return args
+      })
+    // config.plugin('inline-source')
+    //   .use(require('html-webpack-inline-source-plugin'))
+    config.plugins
+      .delete('prefetch')
+      .delete('preload')
+    if (process.env.NODE_ENV === 'production') {
+      // config.plugins.delete('html')
+    }
+    config.resolve.alias
+      .set('@', path.join(__dirname, 'src'))
+    config.module
+      .rule('svg')
+      .exclude.add(resolve('src/icons'))
+      .end()
+    config.module
+      .rule('icons')
+      .test(/\.svg$/)
+      .include.add(resolve('src/icons'))
+      .end()
+      .use('svg-sprite-loader')
+      .loader('svg-sprite-loader')
+      .options({
+        symbolId: 'icon-[name]'
+      })
+      .end()
+    config
+      .when(process.env.NODE_ENV !== 'development',
+        config => {
+          config
+            .plugin('ScriptExtHtmlWebpackPlugin')
+            .after('html')
+            .use('script-ext-html-webpack-plugin', [{
+              // `runtime` must same as runtimeChunk name. default is `runtime`
+              inline: /runtime\..*\.js$/
+            }])
+            .end()
+          config
+            .optimization.splitChunks({
+            chunks: 'all',
+            minSize: 20000, // 允许新拆出 chunk 的最小体积,也是异步 chunk 公共模块的强制拆分体积
+            maxAsyncRequests: 6, // 每个异步加载模块最多能被拆分的数量
+            maxInitialRequests: 6, // 每个入口和它的同步依赖最多能被拆分的数量
+            enforceSizeThreshold: 50000, // 强制执行拆分的体积阈值并忽略其他限制
+            cacheGroups: {
+              vue: {
+                name: 'vue',
+                test: /[\\/]node_modules[\\/]_?vue(.*)/,
+                priority: 10,
+              },
+              elementUI: {
+                name: 'element-ui', // split elementUI into a single package
+                test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
+                priority: 20 // the weight needs to be larger than libs and app or it will be packaged into libs or app
+              },
+              echarts: {
+                name: 'echarts',
+                test: /[\\/]node_modules[\\/]_?echarts(.*)/,
+                priority: 30,
+              },
+              vendors: {
+                name: 'vendors',
+                test: /[\\/]node_modules[\\/]/,
+                priority: -10,
+                chunks: 'initial' // only package third parties that are initially dependent
+              },
+            }
+          })
+          config.optimization.runtimeChunk('single')
+        }
+      )
+  },
+  devServer: {
+    port: 8087,
+    overlay: {
+      warnings: false,
+      errors: false
+    },
+    proxy: {
+      '/permission': {
+        // target: 'http://192.168.0.57:8879',
+        target: 'http://192.168.1.24:8871',
+        ws: true,
+        changeOrigin: true,
+        pathRewrite:{
+          '/api':''
+        }
+      },
+    }
+  }
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 9536 - 0
yarn.lock