Forráskód Böngészése

初始化GM前端

cm 1 éve
commit
66a0673342
100 módosított fájl, 4625 hozzáadás és 0 törlés
  1. 2 0
      .env.development
  2. 2 0
      .env.production
  3. 21 0
      .gitignore
  4. 39 0
      README.md
  5. 5 0
      babel.config.js
  6. 42 0
      package.json
  7. BIN
      public/favicon.ico
  8. 82 0
      public/index.html
  9. 28 0
      src/App.vue
  10. BIN
      src/assets/font/webfont.eot
  11. 66 0
      src/assets/font/webfont.svg
  12. BIN
      src/assets/font/webfont.ttf
  13. BIN
      src/assets/font/webfont.woff
  14. BIN
      src/assets/font/webfont.woff2
  15. 16 0
      src/assets/font/wenfont.css
  16. 1 0
      src/assets/icon/analysis.svg
  17. 1 0
      src/assets/icon/app.svg
  18. 1 0
      src/assets/icon/approval.svg
  19. 1 0
      src/assets/icon/circle.svg
  20. 1 0
      src/assets/icon/clear.svg
  21. 1 0
      src/assets/icon/count.svg
  22. 1 0
      src/assets/icon/crying.svg
  23. 0 0
      src/assets/icon/daiban.svg
  24. 1 0
      src/assets/icon/deal.svg
  25. 1 0
      src/assets/icon/dynamic.svg
  26. 1 0
      src/assets/icon/email.svg
  27. 1 0
      src/assets/icon/favorite.svg
  28. 1 0
      src/assets/icon/feedback.svg
  29. 1 0
      src/assets/icon/finance.svg
  30. 1 0
      src/assets/icon/flag.svg
  31. 0 0
      src/assets/icon/friend.svg
  32. 0 0
      src/assets/icon/github.svg
  33. 1 0
      src/assets/icon/github2.svg
  34. 1 0
      src/assets/icon/group.svg
  35. 1 0
      src/assets/icon/herd.svg
  36. 1 0
      src/assets/icon/horn.svg
  37. 1 0
      src/assets/icon/laugh.svg
  38. 1 0
      src/assets/icon/money.svg
  39. 1 0
      src/assets/icon/news.svg
  40. 0 0
      src/assets/icon/nodejs.svg
  41. 1 0
      src/assets/icon/operating.svg
  42. 0 0
      src/assets/icon/order.svg
  43. 0 0
      src/assets/icon/react.svg
  44. 1 0
      src/assets/icon/reduction.svg
  45. 1 0
      src/assets/icon/refund.svg
  46. 1 0
      src/assets/icon/refuse.svg
  47. 0 0
      src/assets/icon/registration.svg
  48. 1 0
      src/assets/icon/sales.svg
  49. 1 0
      src/assets/icon/screen.svg
  50. 1 0
      src/assets/icon/shelves.svg
  51. 1 0
      src/assets/icon/ship.svg
  52. 0 0
      src/assets/icon/sort.svg
  53. 1 0
      src/assets/icon/u.svg
  54. 1 0
      src/assets/icon/views.svg
  55. 1 0
      src/assets/icon/visitors.svg
  56. 1 0
      src/assets/icon/vue.svg
  57. 1 0
      src/assets/icon/zhuye.svg
  58. 0 0
      src/assets/icon/拒绝.svg
  59. BIN
      src/assets/image/app.jpg
  60. BIN
      src/assets/image/login.jpg
  61. BIN
      src/assets/image/react.jpg
  62. BIN
      src/assets/image/uni.png
  63. BIN
      src/assets/image/vue.png
  64. BIN
      src/assets/logo.png
  65. 97 0
      src/components/Breadcrumb/Breadcrumb.vue
  66. 80 0
      src/components/Breadcrumb/Breadcrumb2.vue
  67. 156 0
      src/components/Dropdown/drop.vue
  68. 66 0
      src/components/Dropdown/empy.vue
  69. 175 0
      src/components/Dropdown/index.vue
  70. 141 0
      src/components/Dropdown/matter.vue
  71. 115 0
      src/components/Dropdown/newsBox.vue
  72. 378 0
      src/components/Headers/Headers.vue
  73. 97 0
      src/components/Home/InformationList.vue
  74. 145 0
      src/components/Index/colleague.vue
  75. 150 0
      src/components/Index/dynamicBox.vue
  76. 135 0
      src/components/Index/fast.vue
  77. 145 0
      src/components/Index/project.vue
  78. 31 0
      src/components/Sidebar/Item.vue
  79. 113 0
      src/components/Sidebar/SidebarItem.vue
  80. 91 0
      src/components/Sidebar/index.vue
  81. 72 0
      src/components/TageView/ScrollPane.vue
  82. 204 0
      src/components/TageView/TagsView.vue
  83. 81 0
      src/components/analyze/cards.vue
  84. 81 0
      src/components/analyze/client.vue
  85. 180 0
      src/components/analyze/map.vue
  86. 125 0
      src/components/analyze/maps.vue
  87. 98 0
      src/components/analyze/monitorcar.vue
  88. 79 0
      src/components/analyze/pay.vue
  89. 114 0
      src/components/analyze/product.vue
  90. 45 0
      src/directive/permission.js
  91. 75 0
      src/http/index.js
  92. 224 0
      src/layout/index.vue
  93. 64 0
      src/main.js
  94. 384 0
      src/router/index.js
  95. 75 0
      src/router/permission.js
  96. 25 0
      src/store/index.js
  97. 92 0
      src/store/modules/permission.js
  98. 78 0
      src/store/modules/tagsView.js
  99. 62 0
      src/store/modules/user.js
  100. 15 0
      src/utils/auth.js

+ 2 - 0
.env.development

@@ -0,0 +1,2 @@
+## base API 测试环境
+VUE_APP_BASE_API = '/api'

+ 2 - 0
.env.production

@@ -0,0 +1,2 @@
+# 上线环境
+VUE_APP_BASE_API = '/api'

+ 21 - 0
.gitignore

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

+ 39 - 0
README.md

@@ -0,0 +1,39 @@
+
+# power
+vue后台管理系统模板
+见文章: https://juejin.im/post/5e670edde51d4527110a9b40
+
+# 说明
+>默认(主)版本为基础框架版
+
+丰富组件 请访问 2.0版本: https://github.com/cgq001/admin-menu/tree/2.0
+
+
+## 初始化
+```
+yarn install
+```
+### 运行
+```
+yarn run serve
+```
+### 打包
+```
+yarn run build
+```
+## 
+## 后台管理通用框架2.0效果图(正在更新中...)
+### 1.登陆
+![Image](https://github.com/cgq001/admin-menu/blob/2.0/image/login.png)
+### 2.工作台
+![Image](https://github.com/cgq001/admin-menu/blob/2.0/image/1.png)
+### 3.通知
+![Image](https://github.com/cgq001/admin-menu/blob/2.0/image/2.png)
+### 4.主题
+![Image](https://github.com/cgq001/admin-menu/blob/2.0/image/3.png)
+### 5.发邮件
+![Image](https://github.com/cgq001/admin-menu/blob/2.0/image/4.png)
+### 6.通知详情
+![Image](https://github.com/cgq001/admin-menu/blob/2.0/image/5.png)
+目前可实现Excel表格下载,请见MarkDown文档,下一步规划图标功能
+

+ 5 - 0
babel.config.js

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

+ 42 - 0
package.json

@@ -0,0 +1,42 @@
+{
+  "name": "power",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build"
+  },
+  "dependencies": {
+    "@jiaminghi/data-view": "^2.10.0",
+    "axios": "^0.19.2",
+    "core-js": "^3.6.4",
+    "echarts": "^4.8.0",
+    "element-ui": "^2.13.0",
+    "js-cookie": "^2.2.1",
+    "nprogress": "^0.2.0",
+    "screenfull": "^5.0.2",
+    "v-charts": "^1.19.0",
+    "vue": "^2.6.11",
+    "vue-count-to": "^1.0.13",
+    "vue-grid-layout": "^2.3.7",
+    "vue-particles": "^1.0.9",
+    "vue-router": "^3.1.5",
+    "vue-seamless-scroll": "^1.1.17",
+    "vue-svg-loader": "^0.16.0",
+    "vue-template-compiler": "^2.6.11",
+    "vuex": "^3.1.2",
+    "wangeditor": "^3.1.1",
+    "xlsx": "^0.15.6"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "^4.2.0",
+    "@vue/cli-service": "^4.2.0",
+    "sass": "^1.25.0",
+    "sass-loader": "^8.0.2",
+    "vue-happy-scroll": "^2.1.1"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions"
+  ]
+}

BIN
public/favicon.ico


+ 82 - 0
public/index.html

@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html lang="ZH">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <!-- <title><%= htmlWebpackPlugin.options.title %></title> -->
+    <title>后台管理系统</title>
+    <style>
+      /*
+ * CSS样式表重置初始化样式,PC端
+ */   html,body,#app{
+        width: 100%;
+        height: 100%;
+      }
+      body,p,div,ul,li,form,input,td,tr,th,div{
+        margin: 0;
+        padding: 0;
+      }
+      body{
+        position: relative;
+      }
+      ul,li{
+        list-style: none;
+      }
+      img{
+        border: none;
+        /* vertical-align: top; */
+        display: block;
+      }
+      a{
+        text-decoration: none;
+        color: #002be5;
+      }
+      a:hover{
+        text-decoration: none;
+      }
+      a img{
+        border: 0;
+      }
+      em{
+        color: #e50000;
+        font-style: normal;
+      }
+      button{
+        cursor: pointer; /*鼠标光标的类型*/
+      }
+      input,textarea{
+        outline: none;
+        appearance: none;
+      }
+      textarea{
+        resize: none;
+        overflow: auto;
+      }
+      table{
+        border-collapse: collapse;
+      }
+      em{
+        font-style: normal;
+      }
+
+    </style>
+      <script>
+        var _hmt = _hmt || [];
+        (function() {
+          var hm = document.createElement("script");
+          hm.src = "https://hm.baidu.com/hm.js?469b8e7d98f12c75e6be0b547061efea";
+          var s = document.getElementsByTagName("script")[0]; 
+          s.parentNode.insertBefore(hm, s);
+        })();
+        </script>  
+  </head>
+  <body>
+    <noscript>
+      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+    </noscript>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+  </body>
+</html>

+ 28 - 0
src/App.vue

@@ -0,0 +1,28 @@
+<template>
+  <div id="app">
+    <router-view/>
+  </div>
+</template>
+
+<script>
+
+export default {
+  mounted(){
+    
+  }
+}
+</script>
+
+<style lang="scss">
+#app {
+  font-family: Avenir, Helvetica, Arial, sans-serif;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  width: 100%;
+  height: 100%;
+}
+// 自定义进度条颜色
+ #nprogress .bar {
+      background: #F811B2 !important; //自定义颜色
+  }
+</style>

BIN
src/assets/font/webfont.eot


+ 66 - 0
src/assets/font/webfont.svg

@@ -0,0 +1,66 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+
+<svg>
+<metadata>
+Created by webfont
+</metadata>
+<defs>
+
+<font id="AlibabaPuHuiTiL" horiz-adv-x="1234" vert-adv-y="1234" >
+  <font-face
+    
+    font-family="AlibabaPuHuiTiL"
+    
+    font-weight="400"
+    
+    font-stretch="normal"
+    
+    units-per-em="1000"
+    
+    ascent="1097"
+    
+    descent="-279"
+    
+  />
+    <missing-glyph />
+    
+    <glyph glyph-name="uni4E0D" unicode="&#x4E0D;" d="M894 686L579 686Q505 536 374.50 388.50Q244 241 82 118L60 148Q215 265 341 405Q467 545 538 686L91 686L91 722L894 722L894 686M475-90L475 510L509 508L509-90L475-90M561 442L582 468Q652 414 756 318.50Q860 223 919 160L894 131Q838 193 735.50 289Q633 385 561 442Z"  horiz-adv-x="984" vert-adv-y="1000"  />
+
+    
+    <glyph glyph-name="uni51FA" unicode="&#x51FA;" d="M813 291L847 289L847-91L813-91L813-38L137-38L137 288L171 286L171-2L475-2L475 379L164 379L164 711L198 709L198 414L475 414L475 807L508 805L508 414L786 414L786 711L820 709L820 379L508 379L508-2L813-2L813 291Z"  horiz-adv-x="984" vert-adv-y="1000"  />
+
+    
+    <glyph glyph-name="uni5C81" unicode="&#x5C81;" d="M798 757L832 755L832 553L145 553L145 758L180 756L180 586L472 586L472 802L507 800L507 586L798 586L798 757M384 532L418 520Q379 451 332 393L812 393L812 360Q723 210 551.50 99.50Q380-11 93-100L77-65Q347 17 514 120Q681 223 768 360L306 360Q278 327 246 294Q310 262 485 168L468 138Q370 197 222 270Q161 209 81 151L60 180Q267 332 384 532Z"  horiz-adv-x="984" vert-adv-y="1000"  />
+
+    
+    <glyph glyph-name="uni6570" unicode="&#x6570;" d="M699 150Q772 41 919-72L899-100Q763 5 679 121Q603 14 440-102L420-73Q582 41 659 151Q569 293 547 487Q518 432 497 399L471 422Q519 496 563 602Q607 708 625 795L657 788Q642 717 603 613L914 613L914 577L819 577Q804 430 777 330Q750 230 699 150M47 307L32 335Q181 420 263 530L52 530L52 560L270 560L270 789L302 787L302 560L495 560L495 530L302 530L302 335L270 335L270 495Q192 393 47 307M210 620L187 604Q116 704 86 740L108 757Q196 639 210 620M464 757L488 740Q448 686 382 601L359 619Q438 719 464 757M571 538Q590 328 678 181Q764 326 786 577L588 577Q584 570 579 557Q574 544 571 538M494 352L475 327Q400 402 319 461L338 485Q349 476 382.50 448Q416 420 446 394Q476 368 494 352M452-12L436-42Q342 9 306 26Q218-37 38-96L26-66Q187-16 275 42Q259 50 112 119Q129 146 169 219L46 219L46 249L184 249Q207 297 219 330L250 320Q234 279 219 249L451 249L451 220Q408 110 334 48Q408 12 452-12M156 132Q191 118 305 63Q374 117 417 219L205 219Q179 168 156 132Z"  horiz-adv-x="984" vert-adv-y="1000"  />
+
+    
+    <glyph glyph-name="uni6C13" unicode="&#x6C13;" d="M176 775L211 779Q240 692 265 590L387 590L387 557L168 557L168 65L356 65L356 32L134 32L134 557L55 557L55 590L230 590Q192 727 176 775M914 109L943 95Q935 35 921-17Q900-90 852-90Q794-90 751-3Q701 98 680 261L456 261L456-37Q479-24 563.50 16Q648 56 660 61L668 28Q660 25 562.50-21Q465-67 452-74Q438-79 418-95L401-67Q422-47 422-37L422 743L866 743L866 483L698 483Q704 354 711 295L929 295L929 261L715 261Q736 106 782 13Q817-53 852-53Q879-53 894 1Q907 48 914 109M833 709L456 709L456 517L833 517L833 709M456 295L676 295Q668 356 663 483L456 483L456 295Z"  horiz-adv-x="984" vert-adv-y="1000"  />
+
+    
+    <glyph glyph-name="uni6D41" unicode="&#x6D41;" d="M318 426Q376 473 505 631L302 631L302 664L573 664Q571 672 555.50 728.50Q540 785 534 806L568 810Q582 765 607 664L884 664L884 631L546 631Q442 498 357 420Q390 422 556.50 426Q723 430 765 432Q760 437 645 548L669 570Q708 535 770 474Q832 413 865 376L842 352Q838 357 795 402Q764 402 558 394.50Q352 387 337 387Q306 385 285 382L279 412Q309 417 318 426M273 616L252 588Q183 654 75 734L96 761Q178 704 273 616M228 387L207 358Q175 390 118 437Q61 484 27 506L47 533Q126 482 228 387M361 237L361 324L394 322Q394 318 393.50 281Q393 244 393 231Q391 105 357 39Q323-27 218-107L195-83Q295-9 326 51.50Q357 112 361 237M886 115L915 105Q915 41 910 1Q904-41 888-55Q872-69 824-71Q802-72 780-71Q738-68 721.50-53.50Q705-39 705 0L705 324L738 322L738 5Q738-21 747.50-29Q757-37 787-39Q804-41 822-39Q858-37 869.50-28Q881-19 883 9Q883 22 884.50 66.50Q886 111 886 115M533-76L533 323L566 321L566-76L533-76M203 266L219 261Q166 67 100-84L68-74Q147 120 187 272L203 266Z"  horiz-adv-x="984" vert-adv-y="1000"  />
+
+    
+    <glyph glyph-name="uni770B" unicode="&#x770B;" d="M906 428L344 428Q311 375 277 333L774 333L774-101L742-101L742-44L276-44L276-102L243-102L243 293Q161 199 46 106L27 134Q203 275 304 428L49 428L49 459L323 459Q359 521 376 563L127 563L127 593L389 593Q406 637 424 703Q243 690 101 686L100 717Q465 725 832 774L836 742Q725 726 458 705Q435 623 424 593L828 593L828 563L412 563Q391 512 362 459L906 459L906 428M742 218L742 304L276 304L276 218L742 218M276 188L276 102L742 102L742 188L276 188M276-13L742-13L742 74L276 74L276-13Z"  horiz-adv-x="984" vert-adv-y="1000"  />
+
+    
+    <glyph glyph-name="uni82F1" unicode="&#x82F1;" d="M319 548L319 639L66 639L66 672L319 672L319 781L353 779L353 672L628 672L628 781L662 779L662 672L912 672L912 639L662 639L662 548L628 548L628 639L353 639L353 548L319 548M929 192L512 192Q550 101 653 37.50Q756-26 933-72L919-106Q743-60 639 4.50Q535 69 491 164Q427-9 64-113L50-78Q235-27 337 39Q439 105 465 192L51 192L51 226L187 226L187 465L473 465L473 585L505 583L505 465L793 465L793 226L929 226L929 192M220 226L472 226Q473 235 473 252L473 431L220 431L220 226M760 431L505 431L505 246Q505 233 504 226L760 226L760 431Z"  horiz-adv-x="984" vert-adv-y="1000"  />
+
+    
+    <glyph glyph-name="uni8DEF" unicode="&#x8DEF;" d="M670 455Q766 383 921 340L910 308Q743 357 644 434Q547 358 402 304L388 335Q526 387 619 456Q553 514 491 617Q453 563 412 517L391 541Q443 599 490.50 675Q538 751 561 817L592 806Q570 749 548 712L837 712L837 679Q772 544 670 455M406 74L408 55L409 40Q341 25 222.50 6Q104-13 27-22L23 10Q32 11 42.50 12.50Q53 14 67 15.50Q81 17 90 18L90 385L121 383L121 22L241 42L241 480L107 480L107 745L358 745L358 480L273 480L273 297L396 297L396 265L273 265L273 47Q298 52 343 61Q388 70 406 74M137 712L137 513L327 513L327 712L137 712M530 680L510 647Q568 541 644 476Q742 557 803 680L530 680M456-80L456 263L814 263L814-80L782-80L782-14L489-14L489-80L456-80M782 230L489 230L489 15L782 15L782 230Z"  horiz-adv-x="984" vert-adv-y="1000"  />
+
+    
+    <glyph glyph-name="uni95EE" unicode="&#x95EE;" d="M139 766L161 791Q219 742 311 642L286 615Q229 681 139 766M857 715L857 45Q857-22 832-44Q807-66 730-72L631-81L621-46L723-38Q784-34 803.50-17Q823 0 823 53L823 680L368 680L368 715L857 715M162-85L127-85L127 609L162 607L162-85M660 137L322 137L322 495L660 495L660 137M628 170L628 461L356 461L356 170L628 170Z"  horiz-adv-x="984" vert-adv-y="1000"  />
+
+    
+    <glyph glyph-name="uni96C4" unicode="&#x96C4;" d="M934 19L934-12L507-12L507-93L475-93L475 534Q430 440 382 372L362 398Q414 473 463 584Q512 695 539 804L572 797Q548 708 514 624L716 624Q693 709 664 794L693 799Q705 766 747 624L915 624L915 590L724 590L724 425L899 425L899 394L724 394L724 229L899 229L899 197L724 197L724 19L934 19M434 588L238 588Q173 370 51 183L31 209Q142 388 205 588L63 588L63 624L216 624Q239 704 253 798L285 795Q272 708 249 624L434 624L434 588M693 425L693 590L507 590L507 425L693 425M315 238L345 249Q390 129 445-46L416-56L397 7Q362 6 151-4Q135-5 113-12L103 18Q123 25 131 39Q173 113 221.50 233Q270 353 299 459L329 450Q300 344 251 223.50Q202 103 159 27Q376 38 386 39Q347 155 315 238M693 229L693 394L507 394L507 229L693 229M507 197L507 19L693 19L693 197L507 197Z"  horiz-adv-x="984" vert-adv-y="1000"  />
+
+    
+    <glyph glyph-name="uniFF0C" unicode="&#xFF0C;" d="M197-136L158-136Q253 1 253 105L298 105Q298-6 197-136Z"  horiz-adv-x="984" vert-adv-y="1000"  />
+
+    
+
+  </font>
+</defs></svg>

BIN
src/assets/font/webfont.ttf


BIN
src/assets/font/webfont.woff


BIN
src/assets/font/webfont.woff2


+ 16 - 0
src/assets/font/wenfont.css

@@ -0,0 +1,16 @@
+@font-face {
+    font-family: 'webfont';
+    font-display: swap;
+    src: url('webfont.eot'); /* IE9 */
+    src: url('webfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
+    url('webfont.woff2') format('woff2'),
+    url('webfont.woff') format('woff'), /* chrome��firefox */
+    url('webfont.ttf') format('truetype'), /* chrome��firefox��opera��Safari, Android, iOS 4.2+*/
+    url('webfont.svg#webfont') format('svg'); /* iOS 4.1- */
+}
+
+html,body,#app{
+    font-family: "webfont" !important;
+    font-size: 16px;
+    font-style: normal;
+}

+ 1 - 0
src/assets/icon/analysis.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585968194325" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4166" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M138.545152 765.825024l95.52896 0c16.662528 0 30.16704-13.50656 30.16704-30.164992L264.241152 309.9648c0-16.662528-13.50656-30.16704-30.16704-30.16704L138.545152 279.79776c-16.662528 0-30.16704 13.50656-30.16704 30.16704l0 425.693184C108.376064 752.318464 121.882624 765.825024 138.545152 765.825024z" p-id="4167"></path><path d="M445.435904 765.825024l95.52896 0c16.662528 0 30.16704-19.744768 30.16704-44.10368L571.131904 99.325952c0-24.36096-13.50656-44.107776-30.16704-44.107776l-95.52896 0c-16.66048 0-30.16704 19.746816-30.16704 44.107776l0 622.395392C415.268864 746.080256 428.773376 765.825024 445.435904 765.825024z" p-id="4168"></path><path d="M752.326656 765.825024l95.52896 0c16.662528 0 30.16704-18.345984 30.16704-40.986624l0-578.3552c0-22.636544-13.50656-40.984576-30.16704-40.984576l-95.52896 0c-16.662528 0-30.16704 18.348032-30.16704 40.984576l0 578.3552C722.157568 747.476992 735.664128 765.825024 752.326656 765.825024z" p-id="4169"></path><path d="M6.144 816.103424l968.704 0 0 50.2784-968.704 0 0-50.2784Z" p-id="4170"></path></svg>

+ 1 - 0
src/assets/icon/app.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585919647172" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6049" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M417.798203 1016.25308c28.670112 16.894887 51.196629 5.631629 51.196629-28.670112V588.76123c0-34.301741-23.038483-68.603482-51.196629-85.49837L87.579948 297.964379c-28.670112-11.263258-51.196629 0-51.196629 28.670112v398.821738c0 34.301741 23.038483 68.603482 51.196629 85.49837l330.218255 205.298481zM138.776577 172.532639c-28.670112 16.894887-28.670112 39.93337 0 56.828258l325.098592 205.298481c28.670112 16.894887 68.603482 16.894887 96.761628 5.631629L885.73539 274.925896c28.670112-16.894887 28.670112-39.93337 0-56.828258L543.229944 12.799157c-23.038483-16.894887-68.603482-16.894887-96.761629 0L138.776577 172.532639z m421.86022 815.050329c0 34.301741 23.038483 45.565 51.196629 28.670112l325.098592-165.365111c28.670112-16.894887 51.196629-51.196629 51.196629-85.49837v-399.333704c0-34.301741-23.038483-45.565-51.196629-28.670112l-325.098592 165.365111c-28.670112 16.894887-51.196629 51.196629-51.196629 85.49837v399.333704z" p-id="6050"></path></svg>

+ 1 - 0
src/assets/icon/approval.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585706174483" class="icon" viewBox="0 0 1026 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6420" xmlns:xlink="http://www.w3.org/1999/xlink" width="128.25" height="128"><defs><style type="text/css"></style></defs><path d="M607.314887 635.882561c-10.094054-3.750445-20.123815-7.30801-30.089283-10.58697-6.322178-2.078818-59.021286-30.367887-21.323958-95.882801l-0.321467 0c65.000566-66.950798 114.656456-174.727866 114.656456-280.811877 0-163.112203-108.462864-248.600914-234.499241-248.600914C309.593862 0 201.709638 85.488711 201.709638 248.600914c0 106.512633 49.441578 214.739755 114.806474 281.519103 25.460163 66.843642-20.188109 91.425129-29.63923 95.175574C50.641721 719.121005 0 845.971764 0 845.971764l0 178.028258 400.740386 0 68.322389-249.286709L607.314887 635.882561 607.314887 635.882561zM859.923419 676.944574l-38.554573-38.640297 0.214311-0.235742-51.627552-51.563258L535.113466 819.247166c-3.214667 2.593165-5.957849 5.893556-7.200854 10.158348l-54.563614 194.594508 199.05218-50.148805c3.986187-1.178711 7.072267-3.643289 9.601139-6.622214l235.399348-233.32053-57.242503-57.199641L859.923419 676.944574 859.923419 676.944574zM537.020835 964.164353c0 0 23.445638-93.311067 27.067496-109.941611 49.848769 21.388251 83.474186 83.452755 83.474186 83.452755L537.020835 964.164353zM791.279563 563.059638l147.46749 147.424628 33.732572-31.632323-147.488921-147.446059L791.279563 563.059638zM1011.248509 560.937958l-70.679811-70.636949c-19.502313-19.502313-50.963187-19.695193-70.251189-0.38576l-21.666855 21.881167 141.273898 141.338192 21.709718-21.94546C1030.922271 611.944007 1030.750822 580.461702 1011.248509 560.937958L1011.248509 560.937958zM1011.248509 560.937958" p-id="6421"></path></svg>

+ 1 - 0
src/assets/icon/circle.svg

@@ -0,0 +1 @@
+<svg t="1591709199521" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6254" width="128" height="128"><path d="M62 512c0 248.528 201.472 450 450 450s450-201.472 450-450c0-248.528-201.472-450-450-450-248.528 0-450 201.472-450 450z" p-id="6255"></path></svg>

+ 1 - 0
src/assets/icon/clear.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585708231073" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10403" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M694.857143 146.285714 694.857143 73.142857c0-40.393143-32.749714-73.142857-73.142857-73.142857L402.285714 0c-40.393143 0-73.142857 32.749714-73.142857 73.142857l0 73.142857L36.571429 146.285714l0 73.142857 109.714286 0 0 731.428571c0 40.393143 32.749714 73.142857 73.142857 73.142857l585.142857 0c40.393143 0 73.142857-32.749714 73.142857-73.142857L877.714286 219.428571l109.714286 0L987.428571 146.285714 694.857143 146.285714zM402.285714 73.142857l219.428571 0 0 73.142857L402.285714 146.285714 402.285714 73.142857zM804.571429 950.857143 219.428571 950.857143 219.428571 219.428571l585.142857 0L804.571429 950.857143z" p-id="10404"></path><path d="M329.142857 329.142857l73.142857 0 0 512-73.142857 0 0-512Z" p-id="10405"></path><path d="M475.428571 329.142857l73.142857 0 0 512-73.142857 0 0-512Z" p-id="10406"></path><path d="M621.714286 329.142857l73.142857 0 0 512-73.142857 0 0-512Z" p-id="10407"></path></svg>

+ 1 - 0
src/assets/icon/count.svg

@@ -0,0 +1 @@
+<svg t="1591698472720" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4277" width="128" height="128"><path d="M825.6 473.6V832H896v64H128v-64h64v-121.6h64V832h128V531.2h64V832h128v-179.2h64V832h128V473.6h57.6zM896 128v268.8h-64V230.4L620.8 441.6l-51.2 44.8-108.8-108.8-275.2 275.2-44.8-44.8 320-320L576 396.8 780.8 192H640V128h256z" p-id="4278"></path></svg>

+ 1 - 0
src/assets/icon/crying.svg

@@ -0,0 +1 @@
+<svg t="1591714008692" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8643" width="128" height="128"><path d="M517.12 53.248q95.232 0 179.2 36.352t145.92 98.304 98.304 145.92 36.352 179.2-36.352 179.2-98.304 145.92-145.92 98.304-179.2 36.352-179.2-36.352T192 838.144t-98.304-145.92-36.352-179.2 36.352-179.2T192 187.904 337.92 89.6t179.2-36.352zM663.552 261.12q-15.36 0-28.16 6.656t-23.04 18.432-15.872 27.648-5.632 33.28q0 35.84 21.504 61.44t51.2 25.6 51.2-25.6 21.504-61.44q0-17.408-5.632-33.28t-15.872-27.648-23.04-18.432-28.16-6.656z m-289.792 0q-29.696 0-50.688 25.088t-20.992 60.928 20.992 61.44 50.688 25.6 50.176-25.6 20.48-61.44-20.48-60.928-50.176-25.088z m146.432 340.992q-51.2 0-97.28 9.728t-82.944 27.648-62.464 41.472-35.84 51.2q-1.024 1.024-1.024 2.048-1.024 3.072-1.024 8.704t2.56 11.776 7.168 11.264 12.8 6.144q25.6-27.648 62.464-50.176 31.744-19.456 79.36-35.328t114.176-15.872q67.584 0 116.736 15.872t81.92 35.328q37.888 22.528 63.488 50.176 17.408-5.12 19.968-18.944t0.512-18.944-3.072-7.168-1.024-3.072q-26.624-55.296-100.352-88.576t-176.128-33.28z"  p-id="8644"></path></svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icon/daiban.svg


+ 1 - 0
src/assets/icon/deal.svg

@@ -0,0 +1 @@
+<svg t="1591669559713" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2407" width="128" height="128"><path d="M699.328 844.544 686.08 844.544l0-34.176c0-18.24-16.768-33.088-37.504-33.088l-517.12 0c-20.736 0-37.568 14.784-37.568 33.088l0 34.176L80.64 844.544c-24.832 0-44.992 19.584-44.992 43.968l0 77.44c0 24.128 20.096 43.904 44.992 43.904l618.688 0c24.896 0 44.992-19.776 44.992-43.904l0-77.44C744.32 864.128 724.16 844.544 699.328 844.544z" p-id="2408" ></path><path d="M803.52 274.944c5.952-2.176 11.328-5.76 15.36-11.072 11.456-14.72 8.384-35.904-6.784-46.976L554.368 27.264C539.2 16.192 517.632 19.072 506.176 33.984c-3.84 4.928-5.76 10.56-6.528 16.192L803.52 274.944z" p-id="2409" ></path><path d="M175.68 469.696C170.752 472 166.272 475.2 162.752 479.744 151.36 494.656 154.368 515.52 169.536 526.72l257.728 189.568c15.168 11.072 36.8 8.128 48.064-6.656 3.904-5.12 6.08-10.88 6.592-16.64L175.68 469.696z" p-id="2410" ></path><path d="M968.896 649.024l-293.568-216 93.696-121.728c4.416-5.568 7.04-11.968 8.256-18.304L498.688 86.784C492.224 89.664 486.336 94.144 481.728 100.032L388.032 221.76 377.408 214.016c-19.84-14.592-48-10.688-62.976 8.768L295.36 247.424C280.384 266.816 284.48 294.4 304.32 308.992l10.496 7.744L217.856 442.624C214.208 447.36 211.84 452.416 210.432 457.856l283.136 206.336c4.288-2.688 8.256-6.144 11.584-10.24L602.112 528l293.568 215.872c20.032 14.72 48.128 10.752 62.976-8.512l19.008-24.896C992.768 691.072 988.8 663.488 968.896 649.024z" p-id="2411"></path></svg>

+ 1 - 0
src/assets/icon/dynamic.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585971308413" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="38172" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M480 480H176.96c-45.056 0-61.952-30.656-38.208-67.904L394.624 49.216C441.792-24.576 480-14.144 480 72.192V480z m0 64v303.04c0 45.056-30.656 61.952-67.904 38.208L49.216 629.376C-24.576 582.208-14.144 544 72.192 544H480z m64 0h303.04c45.056 0 61.952 30.656 38.208 67.904l-255.872 362.88c-47.168 73.792-85.376 63.36-85.376-22.976V544z m0-64V176.96c0-45.056 30.656-61.952 67.904-38.208l362.88 255.872c73.792 47.168 63.36 85.376-22.976 85.376H544z" p-id="38173"></path></svg>

+ 1 - 0
src/assets/icon/email.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585703727879" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1428" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M959.715317 735.848231c0 19.61985-5.520963 37.818327-14.375994 53.829999L662.623029 473.359958l279.655459-244.668419c10.878191 17.269315 17.435805 37.545104 17.435805 59.459207L959.714294 735.848231zM512.000512 530.799158l389.127102-340.471368c-15.959114-8.744151-33.939341-14.100136-53.340998-14.100136l-671.572209 0c-19.429288 0-37.411561 5.355985-53.314391 14.100136L512.000512 530.799158zM620.4836 510.196934l-90.067939 78.861092c-5.27229 4.589528-11.830928 6.885827-18.416173 6.885827-6.588315 0-13.14593-2.296299-18.41822-6.886851l-90.094546-78.861092L117.188711 830.556243c17.161548 10.767228 37.273409 17.216103 59.025697 17.216103l671.572209 0c21.752288 0 41.863125-6.450922 59.024673-17.216103L620.4836 510.196934zM81.719465 228.692562c-10.876144 17.269315-17.433759 37.545104-17.433759 59.459207l0 447.696462c0 19.61985 5.492309 37.818327 14.373948 53.829999l282.69071-316.370461L81.719465 228.692562z" p-id="1429"></path></svg>

+ 1 - 0
src/assets/icon/favorite.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585707762746" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9884" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M542.7 798.8l192.2 122.1c13.2 8.4 30.7 4.5 39.1-8.8 4-6.3 5.4-14 3.7-21.3L718.1 622 918 439.7c11.5-10.6 12.3-28.5 1.8-40-4.8-5.2-11.3-8.5-18.4-9.1l-261.8-23.4-101-251.2c-5.8-14.5-22.3-21.6-36.9-15.7-7.2 2.9-12.9 8.6-15.7 15.7L384.9 367.1l-261.8 23.4c-15.6 1.4-27.1 15.2-25.7 30.8 0.6 7 3.9 13.6 9.1 18.3l200 182.4-59.6 268.9c-3.4 15.3 6.3 30.4 21.6 33.8 7.3 1.6 15 0.3 21.3-3.7l192.1-122.1c18.5-11.9 42.2-11.9 60.8-0.1z" p-id="9885"></path></svg>

+ 1 - 0
src/assets/icon/feedback.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585970363249" class="icon" viewBox="0 0 1128 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="28654" xmlns:xlink="http://www.w3.org/1999/xlink" width="70.5" height="64"><defs><style type="text/css"></style></defs><path d="M980.711066 0.015039H147.538124A145.31649 145.31649 0 0 0 0.153741 148.527364v494.414449A149.546271 149.546271 0 0 0 141.146455 798.973749h46.997571v187.990285c0 44.647693 62.600765 46.997571 92.068242 17.389101L470.129453 798.973749h516.973283a149.546271 149.546271 0 0 0 140.992713-156.031936V148.527364A145.363488 145.363488 0 0 0 980.711066 0.015039zM611.122166 610.983465H235.141597a46.997571 46.997571 0 0 1 0-93.995143h375.980569a46.997571 46.997571 0 0 1 0 93.995143z m278.6486-328.982999H238.478425a46.997571 46.997571 0 1 1 0-93.995142h651.292341a46.997571 46.997571 0 1 1 0 93.995142z m0 0" p-id="28655"></path></svg>

+ 1 - 0
src/assets/icon/finance.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585970013786" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15775" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M375.41487 258.403564h257.849244c79.512983 0 140.28362-165.841364 140.28362-165.841365C773.547734 43.15056 768.436186 5.665868 681.539854 1.690219s-109.614327 56.794988-173.224713 56.794988S408.355963 13.617166 328.27503 1.690219 234.5633 43.15056 234.5633 92.562199c0 0 60.770637 165.841364 140.85157 165.841365z m271.480042 51.115489H375.41487c-301.581385 0-375.41487 567.949878-375.41487 567.949878A149.938768 149.938768 0 0 0 140.85157 1024h738.334842A149.938768 149.938768 0 0 0 1022.309781 875.197132s-73.833484-567.949878-375.414869-567.949879z m31.237243 434.481657a31.805193 31.805193 0 1 1 0 63.042436H544.663933v82.352733a32.941093 32.941093 0 0 1-65.882185 0v-82.352733H344.745576a31.805193 31.805193 0 1 1 0-63.042436h134.036172v-39.756492H344.745576a31.805193 31.805193 0 1 1 0-63.042436h90.871981L340.769927 483.311716a30.669293 30.669293 0 0 1 11.926948-42.596241 34.076993 34.076993 0 0 1 44.86804 11.358997l113.589976 189.12731h5.679498l113.589976-189.12731a34.076993 34.076993 0 0 1 44.86804-11.358997 30.101344 30.101344 0 0 1 11.926948 42.596241l-92.57583 157.890066h85.192481a31.805193 31.805193 0 1 1 0 63.042436H544.663933v39.756492z" p-id="15776"></path></svg>

+ 1 - 0
src/assets/icon/flag.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585714261653" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14511" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M806.1 222.9c-59 0-145.5-19.8-262-94.7C468.6 79.7 395 63.8 331 63.8c-66.6 0-123 17.2-160.6 33V64.2h-50v896h50V662.9c44.9-24.3 116.1-53.8 196.7-53.8 56.4 0 117.3 14.5 177.1 55.2 111.9 76.4 197.6 96.8 257.2 96.8 68.3 0 102.4-26.8 102.4-26.8V198c-0.1 0-31.5 24.9-97.7 24.9z m47.6 480.5c-12 4-29.4 7.7-52.4 7.7-28.5 0-59.7-5.7-92.8-17.1-42.7-14.6-88.5-38.5-136.2-71-62.2-42.4-131.2-63.9-205.3-63.9-77.6 0-146.7 23.8-196.6 47.7V151.7c8.1-4 18.3-8.6 30.2-13.1 29.5-11.3 76.1-24.8 130.5-24.8 65.1 0 127.7 19 186.1 56.5 105.9 68.1 203.2 102.6 289 102.6 16.6 0 32.5-1.3 47.6-3.9v434.4z" fill="" p-id="14512"></path></svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icon/friend.svg


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icon/github.svg


+ 1 - 0
src/assets/icon/github2.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1586270279566" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1262" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M347.8 794.8c0 4-4.6 7.2-10.4 7.2-6.6 0.6-11.2-2.6-11.2-7.2 0-4 4.6-7.2 10.4-7.2 6-0.6 11.2 2.6 11.2 7.2z m-62.2-9c-1.4 4 2.6 8.6 8.6 9.8 5.2 2 11.2 0 12.4-4s-2.6-8.6-8.6-10.4c-5.2-1.4-11 0.6-12.4 4.6z m88.4-3.4c-5.8 1.4-9.8 5.2-9.2 9.8 0.6 4 5.8 6.6 11.8 5.2 5.8-1.4 9.8-5.2 9.2-9.2-0.6-3.8-6-6.4-11.8-5.8zM505.6 16C228.2 16 16 226.6 16 504c0 221.8 139.6 411.6 339 478.4 25.6 4.6 34.6-11.2 34.6-24.2 0-12.4-0.6-80.8-0.6-122.8 0 0-140 30-169.4-59.6 0 0-22.8-58.2-55.6-73.2 0 0-45.8-31.4 3.2-30.8 0 0 49.8 4 77.2 51.6 43.8 77.2 117.2 55 145.8 41.8 4.6-32 17.6-54.2 32-67.4-111.8-12.4-224.6-28.6-224.6-221 0-55 15.2-82.6 47.2-117.8-5.2-13-22.2-66.6 5.2-135.8 41.8-13 138 54 138 54 40-11.2 83-17 125.6-17s85.6 5.8 125.6 17c0 0 96.2-67.2 138-54 27.4 69.4 10.4 122.8 5.2 135.8 32 35.4 51.6 63 51.6 117.8 0 193-117.8 208.4-229.6 221 18.4 15.8 34 45.8 34 92.8 0 67.4-0.6 150.8-0.6 167.2 0 13 9.2 28.8 34.6 24.2C872.4 915.6 1008 725.8 1008 504 1008 226.6 783 16 505.6 16zM210.4 705.8c-2.6 2-2 6.6 1.4 10.4 3.2 3.2 7.8 4.6 10.4 2 2.6-2 2-6.6-1.4-10.4-3.2-3.2-7.8-4.6-10.4-2z m-21.6-16.2c-1.4 2.6 0.6 5.8 4.6 7.8 3.2 2 7.2 1.4 8.6-1.4 1.4-2.6-0.6-5.8-4.6-7.8-4-1.2-7.2-0.6-8.6 1.4z m64.8 71.2c-3.2 2.6-2 8.6 2.6 12.4 4.6 4.6 10.4 5.2 13 2 2.6-2.6 1.4-8.6-2.6-12.4-4.4-4.6-10.4-5.2-13-2z m-22.8-29.4c-3.2 2-3.2 7.2 0 11.8 3.2 4.6 8.6 6.6 11.2 4.6 3.2-2.6 3.2-7.8 0-12.4-2.8-4.6-8-6.6-11.2-4z"  p-id="1263"></path></svg>

+ 1 - 0
src/assets/icon/group.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585971160132" class="icon" viewBox="0 0 1389 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="36786" xmlns:xlink="http://www.w3.org/1999/xlink" width="86.8125" height="64"><defs><style type="text/css"></style></defs><path d="M334.010363 899.782828v-25.635107c0-77.093814 128.364028-148.721319 241.554335-190.001381a89.722874 89.722874 0 0 0 25.729354-102.823168A356.064095 356.064095 0 0 1 503.560207 339.674591 194.430976 194.430976 0 0 1 704.022973 129.127426 197.069884 197.069884 0 0 1 904.485739 339.674591a360.210951 360.210951 0 0 1-102.823168 241.648581c-25.635107 66.632429 10.178645 102.823168 15.267968 102.823168 113.09606 35.813752 246.737904 113.09606 251.827227 190.001381v25.635107c0 103.105908-190.001381 123.368952-364.734793 123.368952-179.728488 0-370.012609-25.729354-370.01261-123.368952z m539.845193-282.74015a450.405058 450.405058 0 0 0 107.818244-277.55658 290.46838 290.46838 0 0 0-102.728921-231.187196 166.628195 166.628195 0 0 1 164.17778-108.100984 182.83863 182.83863 0 0 1 185.289045 200.839753 333.727623 333.727623 0 0 1-87.5552 226.19212c-20.640031 61.448859 10.461386 72.004491 15.550708 72.004491 113.09606 35.813752 236.276518 102.446181 231.187196 179.822735v25.635107c0 76.999567-123.463199 107.818244-256.91655 113.09606-36.096492-102.917414-169.64409-169.832583-256.822302-200.557013z m-873.761309 87.5552V678.962771c0-77.376554 123.463199-144.008983 231.187195-179.822735 5.089323 0 35.907999-10.461386 15.550709-72.004492a332.031182 332.031182 0 0 1-87.5552-226.19212A188.493433 188.493433 0 0 1 344.565996 0.103671a166.910935 166.910935 0 0 1 164.17778 108.100984 289.33742 289.33742 0 0 0-102.728921 231.187196 450.405058 450.405058 0 0 0 107.818244 277.55658c-87.178213 30.72443-221.00855 97.639598-256.91655 200.36852C123.463199 812.510368 0 781.785938 0 704.786371z" p-id="36787"></path></svg>

+ 1 - 0
src/assets/icon/herd.svg

@@ -0,0 +1 @@
+<svg t="1591712944011" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7673" width="128" height="128"><path d="M508.9 467.1h3c69.3-0.8 125.3-56.1 125.3-124.1v-41.4c0-68.6-56.8-124.2-126.8-124.2S383.6 233 383.6 301.6V343c0 68 56 123.3 125.3 124.1z m246 18.1c45 0 81.5-34.8 81.5-77.6v-26c0-42.9-36.5-77.6-81.5-77.6s-81.5 34.8-81.5 77.6v25.9c0 42.9 36.5 77.7 81.5 77.7z m-489 0c45 0 81.5-34.8 81.5-77.6v-26c0-42.9-36.5-77.6-81.5-77.6s-81.5 34.8-81.5 77.6v25.9c-0.1 42.9 36.4 77.7 81.5 77.7z m-117.6 79c-21.4 10.9-36.3 35.3-36.3 63.9V660c0 21.1 12.2 38.7 28.9 44.5 26 6.8 52.6 11.3 79.8 13.8V662c0-50.3 18.2-94.4 45.9-122.3h-0.7c-41.4-0.2-81.1 8.6-117.6 24.5z m724.5 0.1c-36.6-16-76.3-24.8-117.9-24.8h-0.6c27.8 28 45.9 72.1 45.9 122.3v56.4c27.1-2.5 53.8-7 79.6-13.8 16.7-5.7 29.1-23.4 29.1-44.6v-31.6c0-28.6-14.9-52.9-36.1-63.9z m-182.2-3.2c-56-25.7-116.7-39.8-180.2-39.8-63.4 0-123.9 14.1-179.8 39.6C297.9 578.2 275 617.3 275 663v51c0 33.8 18.7 62.1 44.2 71.3 61.6 16.7 125.5 25.9 191.3 25.9 65.7 0 129.5-9 191-25.8 25.7-9.1 44.4-37.5 44.4-71.3v-51c0-45.6-22.8-84.6-55.3-102z" p-id="7674"></path></svg>

+ 1 - 0
src/assets/icon/horn.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585714555316" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="865" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M168.806 511.66A263.12 263.12 0 0 0 360.72 764.61a33.907 33.907 0 0 0 42.045-33.908 33.907 33.907 0 0 0-24.074-33.907 194.628 194.628 0 0 1 0-374.676 33.907 33.907 0 0 0 24.074-33.907 33.907 33.907 0 0 0-42.045-33.907A263.12 263.12 0 0 0 168.806 511.66zM494.994 1024a46.114 46.114 0 0 0 27.804-12.546l10.85-9.494 109.86-89.515L799.82 783.936 940.535 783.93599999a67.815 67.815 0 0 0 67.815-67.81399999l0-400.784a67.815 67.815 0 0 0-67.815-67.815l-131.899 0-160.381-131.90000001-111.216-91.20999999-14.58-11.86700001A46.114 46.114 0 0 0 494.655 0c-11.868 0-20.006 8.816-23.057 24.413a65.78 65.78 0 0 0 0 12.546L471.598 986.702a67.815 67.815 0 0 0 0 14.92C475.328 1016.201 483.804 1024 494.994 1024z m208.19-775.12l81.039 67.814L940.535 316.694 940.53500001 716.122l-164.78900001 0-78.665 64.424-158.686 130.543L538.395 113.25z" p-id="866"></path><path d="M290.194 952.456a33.907 33.907 0 0 0 48.826-30.178 33.907 33.907 0 0 0-19.327-30.516 421.128 421.128 0 0 1 0-756.133 33.907 33.907 0 0 0 19.327-30.516 33.907 33.907 0 0 0-48.826-30.856 488.943 488.943 0 0 0 0 878.538z" p-id="867"></path></svg>

+ 1 - 0
src/assets/icon/laugh.svg

@@ -0,0 +1 @@
+<svg t="1591714761085" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9647" width="128" height="128"><path d="M511.601422 63.74379c-247.565399 0-448.25621 200.694905-448.25621 448.25621 0 247.570515 200.690812 448.257234 448.25621 448.257234 247.566422 0 448.25314-200.686718 448.25314-448.257234C959.854563 264.437671 759.167844 63.74379 511.601422 63.74379zM639.593492 318.832536c8.187473-8.18338 19.071358-12.694113 30.646997-12.694113 23.899316 0 43.341111 19.443841 43.341111 43.344181 0 23.899316-19.440771 43.344181-43.341111 43.344181-23.89727 0-43.338041-19.444864-43.338041-43.344181C626.900402 337.910033 631.407042 327.022055 639.593492 318.832536zM361.954147 306.137399c23.899316 0 43.344181 19.443841 43.344181 43.344181 0 23.899316-19.444864 43.344181-43.344181 43.344181s-43.341111-19.444864-43.341111-43.344181C318.61406 325.582263 338.054831 306.137399 361.954147 306.137399zM740.697167 621.84885c-56.013735 67.348897-138.322345 105.97052-225.819119 105.97052-91.946109 0-176.823218-41.826618-232.873792-114.761744-3.466961-4.517897-4.977361-10.111289-4.245697-15.745612 0.729617-5.64865 3.621481-10.66899 8.126075-14.127765 3.755534-2.908236 8.252964-4.440126 13.008268-4.440126 6.598278 0 12.914124 3.113921 16.885576 8.324596 47.923476 62.342884 120.491235 98.106412 199.095477 98.106412 74.812893 0 145.18259-33.031301 193.07025-90.62195 4.059456-4.859681 10.035564-7.647167 16.397459-7.647167 4.966105 0 9.80225 1.74883 13.615089 4.919033 4.371564 3.629667 7.059789 8.756431 7.583722 14.426571C746.060315 611.926874 744.341161 617.461937 740.697167 621.84885z" p-id="9648"></path></svg>

+ 1 - 0
src/assets/icon/money.svg

@@ -0,0 +1 @@
+<svg t="1591670789244" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3427" width="128" height="128"><path d="M958.057333 64.612385l-164.85323 0-185.357328 249.481452c-49.432885 67.61016-79.667985 112.55149-90.7073 134.823989l-3.15566 0c-32.609691-54.160279-124.625704-182.258429-276.066827-384.305441l-174.316014 0 324.180206 406.776805L121.968801 471.38919l0 89.881061 311.559762 0 0 123.878011L121.968801 685.148261l0 91.034279 311.559762 0 0 180.341928 154.594585 0L588.123149 776.18274l300.518249 0 0-91.034279L588.125547 685.148461l0-123.878011 300.518249 0 0-89.881061L630.721467 471.38939 958.057333 64.612385z" p-id="3428"></path></svg>

+ 1 - 0
src/assets/icon/news.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585713715390" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14046" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M656.695652 857.043478a133.565217 133.565217 0 1 1-267.130435 0h-244.869565l66.782609-133.565217v-333.913044h2.470956c12.889043-116.224 91.848348-212.257391 198.500174-249.87826-0.26713-2.025739-0.623304-4.029217-0.623304-6.12174a100.173913 100.173913 0 0 1 200.347826 0c0 2.092522-0.356174 4.096-0.623304 6.12174 106.651826 37.62087 185.61113 133.654261 198.500174 249.87826h2.470956v333.913044l66.782609 133.565217h-222.608696z m-133.565217 89.043479a89.043478 89.043478 0 0 0 89.043478-89.043479h-178.086956a89.043478 89.043478 0 0 0 89.043478 89.043479z m-11.130435-868.173914a55.474087 55.474087 0 0 0-55.05113 49.619479A303.059478 303.059478 0 0 1 512 122.434783c18.810435 0 37.197913 1.80313 55.05113 5.097739A55.474087 55.474087 0 0 0 512 77.913043z m256 645.565218v-311.652174h-0.556522c-5.87687-136.192-117.826783-244.869565-255.443478-244.869565-137.616696 0-249.566609 108.677565-255.443478 244.869565H256v311.652174l-44.521739 89.043478h601.043478l-44.521739-89.043478z"  p-id="14047"></path></svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icon/nodejs.svg


+ 1 - 0
src/assets/icon/operating.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585967668993" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3407" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M192.124455 135.876923H84.210609A13.233231 13.233231 0 0 1 70.662302 122.407385V14.493538C70.662302 6.695385 76.491225 0.866462 84.13184 0.866462h107.992615c7.640615 0 13.548308 5.828923 13.548308 13.469538v107.913846a13.233231 13.233231 0 0 1-13.548308 13.548308z m809.826462 0H319.573071a13.233231 13.233231 0 0 1-13.548308-13.469538V14.493538c0-7.719385 5.907692-13.548308 13.548308-13.548307h682.456615c7.719385 0 13.548308 5.828923 13.548308 13.469538v107.913846a13.233231 13.233231 0 0 1-13.548308 13.548308zM192.203225 541.696H84.053071A13.233231 13.233231 0 0 1 70.662302 528.226462v-107.913847c0-7.719385 5.828923-13.548308 13.469538-13.548307h107.992615c7.640615 0 13.548308 5.828923 13.548308 13.469538v107.992616a13.548308 13.548308 0 0 1-13.548308 13.469538z m809.747692 0H319.573071a13.233231 13.233231 0 0 1-13.548308-13.469538v-107.913847c0-7.719385 5.907692-13.548308 13.548308-13.548307h682.456615c7.719385 0 13.548308 5.828923 13.548308 13.469538v107.992616a13.548308 13.548308 0 0 1-13.548308 13.469538zM192.124455 947.593846H84.210609A13.233231 13.233231 0 0 1 70.662302 933.966769v-107.913846c0-7.719385 5.828923-13.548308 13.469538-13.548308h107.992615c7.640615 0 13.548308 5.828923 13.548308 13.469539v107.992615a13.548308 13.548308 0 0 1-13.548308 13.469539z m809.826462 0H319.573071a13.233231 13.233231 0 0 1-13.548308-13.548308v-107.913846c0-7.719385 5.907692-13.548308 13.548308-13.548307h682.456615c7.719385 0 13.548308 5.828923 13.548308 13.469538v107.992615a13.548308 13.548308 0 0 1-13.548308 13.469539z"  p-id="3408"></path></svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icon/order.svg


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icon/react.svg


+ 1 - 0
src/assets/icon/reduction.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1586270995099" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3639" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M879.787 101.787c11.716-11.716 30.71-11.716 42.426 0 11.716 11.716 11.716 30.71 0 42.426l-262 262c-11.716 11.716-30.71 11.716-42.426 0-11.716-11.716-11.716-30.71 0-42.426l262-262z m-517 517c11.716-11.716 30.71-11.716 42.426 0 11.716 11.716 11.716 30.71 0 42.426l-261 261c-11.716 11.716-30.71 11.716-42.426 0-11.716-11.716-11.716-30.71 0-42.426l261-261zM144.213 101.787c-11.716-11.716-30.71-11.716-42.426 0-11.716 11.716-11.716 30.71 0 42.426l261 261c11.716 11.716 30.71 11.716 42.426 0 11.716-11.716 11.716-30.71 0-42.426l-261-261z m515 515c-11.716-11.716-30.71-11.716-42.426 0-11.716 11.716-11.716 30.71 0 42.426l263 263c11.716 11.716 30.71 11.716 42.426 0 11.716-11.716 11.716-30.71 0-42.426l-263-263z"  p-id="3640"></path><path d="M851.573 366.064c16.569 0 30 13.431 30 30 0 16.568-13.431 30-30 30H658c-33.137 0-60-26.863-60-60V172c0-16.569 13.431-30 30-30 16.569 0 30 13.431 30 30v194.064h193.573zM658 851.866c0 16.569-13.431 30-30 30-16.569 0-30-13.431-30-30V657c0-33.137 26.863-60 60-60h194.573c16.569 0 30 13.431 30 30 0 16.569-13.431 30-30 30H658v194.866zM173 658c-16.569 0-30-13.431-30-30 0-16.569 13.431-30 30-30h194.504c33.137 0 60 26.863 60 60v193.866c0 16.569-13.432 30-30 30-16.569 0-30-13.431-30-30V658H173z m194.504-486c0-16.569 13.431-30 30-30 16.568 0 30 13.431 30 30v194.064c0 33.137-26.863 60-60 60H173c-16.569 0-30-13.432-30-30 0-16.569 13.431-30 30-30h194.504V172z" p-id="3641"></path></svg>

+ 1 - 0
src/assets/icon/refund.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585970239231" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="20420" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M1020.439 264.843H3.561V116.542c0-27.3 21.971-49.434 49.078-49.434h918.713c13.01 0 25.505 5.208 34.708 14.475 9.203 9.273 14.379 21.847 14.379 34.959v148.301z m0 98.861v543.754c0 27.304-21.981 49.434-49.087 49.434H52.639a48.911 48.911 0 0 1-34.708-14.475c-9.212-9.273-14.37-21.841-14.37-34.959V363.704h1016.878zM445.365 610.862V487.285L224.458 709.73h550.525v-98.867H445.365z m0 0" p-id="20421"></path></svg>

+ 1 - 0
src/assets/icon/refuse.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585707534504" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7641" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M512 62C264.5 62 62 264.5 62 512s202.5 450 450 450 450-202.5 450-450S759.5 62 512 62z m0 82.5c84.375 0 161.25 28.125 223.125 76.875l-513.75 513.75C172.625 673.25 144.5 596.375 144.5 512c0-202.5 165-367.5 367.5-367.5z m0 735c-90 0-170.625-31.875-234.375-84.375l517.5-517.5c52.5 63.75 84.375 146.25 84.375 234.375 0 202.5-165 367.5-367.5 367.5z" p-id="7642"></path></svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icon/registration.svg


+ 1 - 0
src/assets/icon/sales.svg

@@ -0,0 +1 @@
+<svg t="1591696292213" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6816" width="128" height="128"><path d="M928 12.8h-832C51.2 12.8 12.8 51.2 12.8 96v832c0 44.8 38.4 83.2 83.2 83.2h832c44.8 0 83.2-38.4 83.2-83.2v-832c0-44.8-38.4-83.2-83.2-83.2z m-147.2 518.4c-19.2 128-134.4 230.4-268.8 230.4s-249.6-102.4-268.8-230.4c-25.6-6.4-44.8-32-44.8-57.6 0-32 25.6-64 64-64s64 25.6 64 64c0 25.6-12.8 51.2-38.4 57.6 19.2 108.8 115.2 192 224 192s211.2-83.2 224-192c-19.2-12.8-32-32-32-57.6 0-32 25.6-64 64-64 32 0 64 25.6 64 64-6.4 25.6-25.6 51.2-51.2 57.6z m172.8-371.2c0 25.6-19.2 44.8-44.8 44.8H115.2c-25.6 0-44.8-19.2-44.8-44.8v-44.8c0-25.6 19.2-44.8 44.8-44.8h793.6c25.6 0 44.8 19.2 44.8 44.8v44.8z"  p-id="6817"></path></svg>

+ 1 - 0
src/assets/icon/screen.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1586270353079" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3069" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M131.413333 85.333333h142.933334a32 32 0 1 0 0-64H54.186667a32 32 0 0 0-32 32v221.013334a32 32 0 1 0 64 0V131.413333l344.32 344.32a32 32 0 0 0 45.226666-45.226666zM969.813333 717.653333a32 32 0 0 0-32 32v142.506667l-344.32-344.32a32 32 0 0 0-45.226666 45.226667l344.32 345.6h-142.933334a32 32 0 0 0 0 64h220.16a32 32 0 0 0 32-32v-221.013334a32 32 0 0 0-32-32zM999.253333 42.666667a32 32 0 0 0-29.44-19.626667h-220.16a32 32 0 1 0 0 64h142.506667l-344.32 344.32a32 32 0 1 0 45.226667 45.226667L938.666667 131.413333v142.933334a32 32 0 1 0 64 0V54.186667a32 32 0 0 0-3.413334-11.52zM430.506667 548.266667L85.333333 892.586667v-142.933334a32 32 0 1 0-64 0v220.16a32 32 0 0 0 32 32h221.013334a32 32 0 1 0 0-64H131.413333l344.32-344.32a32 32 0 0 0-45.226666-45.226666z"  p-id="3070"></path></svg>

+ 1 - 0
src/assets/icon/shelves.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585968434943" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11052" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M721.329 104.684c13.44-12.544 35.335-12.544 48.832 0L949.92 300.18c13.44 12.544 13.44 32.816 0 45.304l-122.304 3.304v345.968c0 16.968-14.952 30.856-33.264 30.856h-97.159c-18.313 0-33.264-13.888-33.264-30.856V348.787L541.4 345.483c-13.496-12.544-13.496-32.816 0-45.304l179.929-195.495zM98.72 474.732h411.824c-0.112-11.649-0.28-23.408-0.504-35.28a5829.023 5829.023 0 0 1-0.503-43.344c-0.056-8.624-0.113-17.135-0.113-25.592v-3.92H98.72c-19.152 0-34.72 15.512-34.72 34.665v38.752c0 19.15 15.512 34.719 34.72 34.719zM98.72 701.812h241.136c-0.056-0.056-0.056-0.056-0.056-0.112h170.744c-0.112-11.649-0.28-23.408-0.504-35.28a2858.722 2858.722 0 0 1-0.503-43.344c-0.056-8.568-0.113-17.135-0.113-25.592v-3.92H98.72c-19.152 0-34.72 15.512-34.72 34.665V667.093c0 19.207 15.512 34.719 34.72 34.719zM922.816 820.643H98.72c-19.152 0-34.72 15.513-34.72 34.665v38.752c0 19.152 15.512 34.664 34.72 34.664h824.152c19.153 0 34.665-15.512 34.665-34.664v-38.752c0-19.152-15.569-34.665-34.721-34.665zM98.72 139.627H510.6l-12.375 16.576a9207.86 9207.86 0 0 0-33.993 46.032l-33.599 45.528H98.72c-19.152 0-34.72-15.512-34.72-34.665v-38.752c0-19.15 15.512-34.719 34.72-34.719z" fill="" p-id="11053"></path></svg>

+ 1 - 0
src/assets/icon/ship.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585970463113" class="icon" viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="32766" xmlns:xlink="http://www.w3.org/1999/xlink" width="64.0625" height="64"><defs><style type="text/css"></style></defs><path d="M1.125275 980.339341c0 23.405714 19.12967 42.535385 42.535384 42.535384h937.803956c23.405714 0 42.535385-19.12967 42.535385-42.535384v-724.676923H1.125275v724.676923z m595.720439-383.493627h256.787693V681.916484H596.845714v-85.07077z m-85.295824 170.366594h342.083517v85.295824h-342.083517v-85.295824z m-21.38022-554.085275H0l102.4-180.043956C118.378901 11.702857 142.684835 0 169.466374 0h320.703296v213.127033z m534.955605 0H534.955604V0h320.703297C882.215385 0 906.746374 12.828132 922.725275 33.083077l102.4 180.043956z m0 0" fill="" p-id="32767"></path></svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icon/sort.svg


+ 1 - 0
src/assets/icon/u.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585919708367" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10664" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M870.515838 62.986543l0 565.154617c0 111.332644-31.92613 194.434318-95.733365 249.309112-60.59303 51.635007-147.84728 77.449953-261.761726 77.449953-50.895157 0-96.941889-6.460132-138.14736-19.371186-56.559157-17.742083-102.605889-46.37419-138.149407-85.913718-45.249577-50.823526-67.858504-121.005958-67.858504-210.568786L168.865477 62.986543l185.411827 0 0 563.791573c0 57.271378 14.538111 100.631932 43.62252 130.062218 29.084409 29.443589 66.231447 44.155662 111.48921 44.155662 60.59303 0 105.011682-14.112416 133.299959-42.341341 28.27088-28.230971 42.412972-69.37709 42.412972-123.412774L685.101965 62.986543 870.515838 62.986543z" p-id="10665"></path></svg>

+ 1 - 0
src/assets/icon/views.svg

@@ -0,0 +1 @@
+<svg t="1591694869313" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3583" width="128" height="128"><path d="M92.161 959.999h839.68c15.553 0 28.16-12.609 28.16-28.16s-12.608-28.16-28.16-28.16h-811.52V92.159c0-15.553-12.608-28.16-28.16-28.16s-28.16 12.608-28.16 28.16v839.68c0 15.552 12.608 28.16 28.16 28.16z m135.803-219.165c32.945 0 59.647-30.339 59.647-67.757 0-9.026-1.567-17.634-4.387-25.51l117.759-153.753a53.084 53.084 0 0 0 17.855 3.092c17.38 0 33.018-8.449 43.919-21.922l111.182 63.334c0.36 37.068 26.92 67.002 59.63 67.002 32.944 0 59.647-30.34 59.647-67.758 0-1.254-0.035-2.496-0.094-3.732l154.882-151.144c7.387 3.723 15.554 5.807 24.154 5.807 32.946 0 59.648-30.333 59.648-67.758 0-37.419-26.702-67.757-59.648-67.757-32.933 0-59.647 30.338-59.647 67.757 0 7.711 1.15 15.112 3.24 22.017L670.74 484.59c-10.196-9.246-23.11-14.787-37.173-14.787-16.215 0-30.912 7.365-41.665 19.297l-113.574-64.602c-2.106-35.248-27.924-63.108-59.491-63.108-32.935 0-59.648 30.34-59.648 67.758 0 10.268 2.022 19.996 5.621 28.717L248.922 609.631c-6.52-2.78-13.581-4.312-20.958-4.312-32.935 0-59.648 30.338-59.648 67.758 0 37.418 26.713 67.757 59.648 67.757z"  p-id="3584"></path></svg>

+ 1 - 0
src/assets/icon/visitors.svg

@@ -0,0 +1 @@
+<svg t="1591702671993" class="icon" viewBox="0 0 1093 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4415" width="128" height="128"><path d="M682.666667 0 477.866667 0l0 819.2 204.8 0L682.666667 0zM341.333333 409.6 136.533333 409.6l0 409.6 204.8 0L341.333333 409.6zM1024 273.066667l-204.8 0 0 546.133333 204.8 0L1024 273.066667zM0 887.466667l0 136.533333 72.021333 0L1092.266667 1024l0-67.720533L1092.266667 887.466667 0 887.466667z" p-id="4416"></path></svg>

+ 1 - 0
src/assets/icon/vue.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585919576218" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3412" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M512 504L764.8 68.8h-134.4L512 275.2 393.6 70.4h-134.4L512 504zM819.2 70.4L512 600 204.8 68.8H0l512 886.4L1024 70.4H819.2z" p-id="3413"></path></svg>

+ 1 - 0
src/assets/icon/zhuye.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1585705087269" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2224" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M950.3 489.4L533.8 73c-12-12-31.5-12-43.5 0L73.9 489.4c-19.4 19.4-5.7 52.5 21.7 52.5h66.8v353.7c0 35.3 28.7 64 64 64H384V831.8c0-35.3 28.7-64 64-64h128c35.3 0 64 28.7 64 64v127.8h156.6c35.3 0 64-28.7 64-64V541.9h67.8c27.5 0 41.2-33.2 21.9-52.5z" fill="" p-id="2225"></path></svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
src/assets/icon/拒绝.svg


BIN
src/assets/image/app.jpg


BIN
src/assets/image/login.jpg


BIN
src/assets/image/react.jpg


BIN
src/assets/image/uni.png


BIN
src/assets/image/vue.png


BIN
src/assets/logo.png


+ 97 - 0
src/components/Breadcrumb/Breadcrumb.vue

@@ -0,0 +1,97 @@
+<template>
+<!-- 面包屑 -->
+    <el-breadcrumb class="app-breadcrumb" separator="/">
+        <transition-group name="breadcrumb">
+            <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
+                <span
+                    v-if="item.redirect === 'noRedirect' || index === levelList.length-1"
+                    class="no-redirect"
+                    >
+                    {{item.meta.title}}
+                </span>
+                <a v-else @click.prevent="handleLink(item)">{{item.meta.title}}</a>
+            </el-breadcrumb-item>
+        </transition-group>
+    </el-breadcrumb>
+</template>
+
+<script>
+import pathToRegexp from 'path-to-regexp'
+export default {
+    data(){
+        return {
+            levelList:null
+        }
+    },
+    watch:{
+        $route: {
+            handler(route){
+                this.getBreadcrumb()
+            },
+            immediate: true
+        }
+    },
+    methods:{
+        getBreadcrumb(){
+             
+            // 面包屑仅显示包含meta.title 且 item.meta.breadcrumb不为falsed 的路由
+            let metched = this.$route.matched.filter(
+                item => item.meta && item.meta.title && item.meta.breadcrumb !== false
+            )
+
+            // 跟路由
+            const first = metched[0];
+            
+
+            // 根匹配只要不是home,就作为home下一级
+            if(!this.isHome(first)){
+                metched = [{ refirect: '/index', meta: { title: '首页' }}].concat(metched)
+            }
+             
+            // 处理完指定到levelList
+            this.levelList = metched
+        },
+        isHome(route){
+            const name = route && route.name;
+            if(!name){
+                return false
+            }
+            return name.trim().toLocaleLowerCase() === "Home".toLocaleLowerCase()
+        },
+        pathCompile(path){
+            const { params } = this.$route;
+            var toPath = pathToRegexp.compile(path);
+            return thPath(params);
+        },
+        handleLink(iten){
+            const { redirect, path } = item;
+            // 若存在重定向 按重定向走
+            if(redirect){
+                this.$router.push(redirect)
+                return;
+            }
+            // 编译path, 避免存在路径参数
+            this.$router.push(this.pathCompile(path))
+        }
+    }
+}
+</script>
+
+<style scoped>
+.breadcrumb-enter-active,
+.breadcrumb-leave-active{
+    transform: all .5s;
+}
+
+.breadcrumb-enter,
+.breadcrumb-leave-active{
+    opacity: 0;
+    transform: translateX(20px);
+}
+.breadcrumb-move{
+    transition: all 0.5s;
+}
+/* .breadcrumb-leave-active{
+    position: absolute;;
+} */
+</style>

+ 80 - 0
src/components/Breadcrumb/Breadcrumb2.vue

@@ -0,0 +1,80 @@
+<template>
+    <el-breadcrumb class="app-breadcrumb" separator="/">
+        <transition-group name="breadcrumb"  mode="out-in">
+        
+            <el-breadcrumb-item v-for="(item,index)  in levelList" :key="item.path" v-if='item.meta.title'>
+                <span v-if='item.redirect==="index"||index==levelList.length-1' class="no-redirect">{{item.meta.title}}</span>
+                <router-link v-else :to="item.redirect||item.path">{{item.meta.title}}</router-link>
+            </el-breadcrumb-item>
+       
+        </transition-group>
+    </el-breadcrumb>
+</template>
+
+<script>
+    export default {
+      created() {
+        this.getBreadcrumb()
+      },
+      data() {
+        return {
+          levelList: null
+        }
+      },
+      watch: {
+        $route() {
+           
+          this.getBreadcrumb()
+        }
+      },
+      methods: {
+        getBreadcrumb() {
+          let matched = this.$route.matched.filter(
+                item => item.meta && item.meta.title && item.meta.breadcrumb !== false
+            )
+         
+          const first = matched[0]
+          if (first && first.name !== 'index') {
+            matched = [{ path: '/index', meta: { title: '首页' }}].concat(matched)
+          }
+          this.levelList = matched
+        }
+      }
+    }
+</script>
+
+<style scoped>
+    /* .app-breadcrumb.el-breadcrumb {
+        display: inline-block;
+        font-size: 14px;
+        line-height: 50px;
+        margin-left: 10px;
+    }
+    .no-redirect {
+            color: #97a8be;
+            cursor: text;
+        } */
+    .breadcrumb-enter-active,
+    .breadcrumb-leave-active{
+        transition: all 0.5s;
+    }
+    /* .breadcrumb-enter,.breadcrumb-leave-to{
+        opacity: 0;
+        transform: translateX(20px);
+    }
+    .breadcrumb-enter-to,.breadcrumb-leave{
+        opacity: 1;
+        transform: translateX(0px);
+    } */
+    .breadcrumb-enter,
+    .breadcrumb-leave-active{
+        opacity: 0;
+        transform: translateX(20px);
+    }
+    .breadcrumb-move{
+        transition: all 0.5s;
+    }
+    .breadcrumb-leave-active{
+        position: absolute;;
+    }
+</style>

+ 156 - 0
src/components/Dropdown/drop.vue

@@ -0,0 +1,156 @@
+<template>
+    <div class="drop">
+        <div class="drop-left" :style="{background: iconBgColor}">
+            <Email v-if="type === 'Email'" class="drop-left-icon" :style="{color: iconColor}" />
+            <Zhuye v-if="type === 'Zhuye'" class="drop-left-icon" :style="{color: iconColor}" />
+            <Friend v-if="type === 'Friend'" class="drop-left-icon" :style="{color: iconColor}" />
+            <Approval v-if="type === 'Approval'" class="drop-left-icon" :style="{color: iconColor}" />
+            <Refuse v-if="type === 'Refuse'" class="drop-left-icon" :style="{color: iconColor}" />
+            <Favorite v-if="type === 'Favorite'" class="drop-left-icon" :style="{color: iconColor}" />
+        </div>
+        <div class="drop-right">
+            <p>{{text}}</p>
+            <p>{{time}}</p>
+        </div>
+    </div>
+</template>
+
+<script>
+import Email from '@/assets/icon/email.svg' // 邮件
+import Zhuye from '@/assets/icon/zhuye.svg'  // 主页
+import Friend from '@/assets/icon/friend.svg' // 朋友
+import Approval from '@/assets/icon/approval.svg' //批准
+import Refuse from '@/assets/icon/refuse.svg' //拒绝
+import Favorite from '@/assets/icon/favorite.svg' // 收藏
+export default {
+    props:{
+        type:{
+            type: String,
+            default: 'Zhuye',
+            validator: function (value) {
+                // 这个值必须匹配下列字符串中的一个
+                return ['Zhuye', 'Email','Friend','Approval','Refuse','Favorite'].indexOf(value) !== -1
+            }
+        },
+        text:{
+            type: String,
+            default: 'Zhuye',
+            required: true
+        },
+        time:{
+            type: String,
+            required: true
+        },
+        iconColor:{
+            type: String,
+            default: '#ffffff',
+            validator: function (value) {
+                let colorHtml = /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/
+                let colorRgba = /^[rR][gG][Bb][Aa]?[\(]((2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?),){2}(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?),?(0\.\d{1,2}|1|0)?[\)]{1}$/
+                // 必须匹配一个颜色的正则
+                if(colorHtml.test(value)){
+                    return true
+                }
+                 if(colorRgba.test(value)){
+                    return true
+                }
+                return false;
+            }
+        },
+        iconBgColor: {
+            type: String,
+            default: '#94E273',
+            validator: function (value) {
+                let colorHtml = /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/
+                let colorRgba = /^[rR][gG][Bb][Aa]?[\(]((2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?),){2}(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?),?(0\.\d{1,2}|1|0)?[\)]{1}$/
+                // 必须匹配一个颜色的正则
+                if(colorHtml.test(value)){
+                    return true
+                }
+                 if(colorRgba.test(value)){
+                    return true
+                }
+                return false;
+            }
+        }
+    },
+    components:{
+        Email,
+        Zhuye,
+        Friend,
+        Approval,
+        Refuse,
+        Favorite
+    }
+}
+</script>
+
+<style scoped>
+.drop{
+    width: 300px;
+    min-height: 65px !important;
+    max-height: 87px !important;
+    border-bottom: 1px solid #dcdfe6;
+    padding: 12px 24px;
+    box-sizing: border-box;
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+
+}
+.drop:hover{
+    background: #E2EFFD;
+}
+.drop:hover .drop-left-icon{
+    transform: rotate(360deg);
+    opacity: 1;
+}
+.drop-left{
+    width: 32px;
+    height: 32px;
+    background: burlywood;
+    border-radius: 16px;
+    margin-right: 10px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.drop-left-icon{
+    width: 20px;
+    height: 20px;
+    fill: currentColor; 
+    opacity: 0.9;
+    transition: all 0.5s;
+}
+.drop-right{
+    flex: 1;
+    display: flex;
+    align-items: stretch;
+    flex-wrap: wrap;
+}
+.drop-right p{
+    width: 100%;
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+.drop-right p:nth-child(1){
+    font-size: 14px;
+    font-weight: 400;
+    line-height: 22px;
+    color: #515a6e;
+    margin-bottom: 5px;
+    max-height: 44px;
+    min-height: 22px;
+    text-overflow: -o-ellipsis-lastline;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    display: -webkit-box;
+    -webkit-line-clamp: 2;
+    -webkit-box-orient: vertical;
+}
+.drop-right p:nth-child(2){
+    font-size: 12px;
+    color: #808695;
+}
+
+</style>

+ 66 - 0
src/components/Dropdown/empy.vue

@@ -0,0 +1,66 @@
+<template>
+    <div class="empy">
+        <div class="empy-box">
+             <News v-if="type == 'News'" class="empy-icon" />
+             <Flag v-if="type == 'Flag'" class="empy-icon" />
+             <Horn v-if="type == 'Horn'" class="empy-icon" />
+        </div>
+        <p>{{text}}</p>
+    </div>
+</template>
+
+<script>
+// 消息图标
+import News from '@/assets/icon/news.svg'
+// 代办图标
+import Flag from '@/assets/icon/flag.svg'
+// 通知 图标
+import Horn from '@/assets/icon/horn.svg'
+export default {
+    props:{
+        type:{
+            type: String,
+            default: 'News',
+            validator: function (value) {
+                // 这个值必须匹配下列字符串中的一个
+                return ['Flag', 'News','Horn'].indexOf(value) !== -1
+            }
+        },
+        text:{
+            type: String,
+            default: '你没有新的消息'
+        },
+    },
+    components: {
+        News,
+        Flag,
+        Horn
+    }
+}
+</script>
+
+<style scoped>
+.empy{
+    width: 100%;
+    height: 330px;
+    padding-top: 70px;
+    box-sizing: border-box;
+}
+.empy-box{
+    width: 100%;
+    height: auto;
+    display: flex;
+    justify-content: center;
+}
+.empy-icon{
+    fill: currentColor;
+    color: #DAE0E5;
+    width: 85px;
+}
+.empy p{
+    color: #8C8C8C;
+    font-size: 14px;
+    width: 100%;
+    text-align: center;
+}
+</style>

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

@@ -0,0 +1,175 @@
+<template>
+    <el-tabs class="dropdowns" v-model="activeName"  @tab-click="handleClick">
+        <el-tab-pane label="通知" name="first" style="padding:0; " class="dropdowns-dropBox">
+          
+            <div class="dropdowns-list-box">
+              <Drop type='Email' iconColor='#ffffff' iconBgColor='#3593FE' text='您有一封新邮件,注意查收' time='04-01 12:20' style="background: #AFFCDD" />
+              <Drop type='Friend' iconColor='#ffffff' iconBgColor='#87D068' text='您有新朋友通过了你的好友验证' time='04-01 12:20' />
+              <Drop type='Approval' iconColor='#ffffff' iconBgColor='#F06292' text='您提交的文件,已批复' time='04-01 12:20' />
+              <Drop type='Refuse' iconColor='#ffffff' iconBgColor='#FE5C57' text='您的请假申请被拒绝,请准时上班' time='04-01 12:20' />
+              <Drop type='Favorite' iconColor='#ffffff' iconBgColor='#FF9900' text='您有一篇文字被用户admin收藏,请注意查看' time='04-01 12:20' />
+              <Drop text='您有一封新邮件,注意查收' time='04-01 12:20' />
+              <Drop text='您有一封新邮件,注意查收' time='04-01 12:20' />
+              <Drop text='您有一封新邮件,注意查收' time='04-01 12:20' />
+              <Drop type='Favorite' iconColor='#ffffff' iconBgColor='#FF9900' text='您有一篇文字被用户admin收藏,请注意查看' time='04-01 12:20' />
+              <el-button class="dropdowns-more"  :loading="true" type="text" disabled>加载更多</el-button>
+            </div>
+            <div class="dropdowns-foots">
+                  <!-- <Clear class="dropdowns-foots-iconsClear"  /> -->
+                  清空通知
+            </div>
+            <!-- <Empy type='Horn' text='你还没有新的通知' /> -->
+        </el-tab-pane>
+        <el-tab-pane label="消息" name="second" style="padding:0"  class="dropdowns-dropBox">
+            <div class="dropdowns-list-box">
+              <NewsBox text='小明给你发了一条消息' time='04-10 20:20' />
+            </div>
+            <div class="dropdowns-foots">
+                清空通知
+            </div>
+            <!-- <Empy type='News' text='你还没有新的消息' /> -->
+        </el-tab-pane>
+        <el-tab-pane label="代办" name="third" style="padding:0">
+            <div class="dropdowns-list-box">
+              <Matter type='info' text='小明给你发了一条消息' time='需要在下午五点前完成' />
+              <Matter type='primary' text='小明给你发了一条消息' time='需要在下午五点前完成' />
+              <Matter type='success' text='小明给你发了一条消息' time='需要在下午五点前完成' />
+              <Matter type='warning' text='小明给你发了一条消息' time='需要在下午五点前完成' />
+              <Matter type='danger' text='小明给你发了一条消息' time='需要在下午五点前完成' />
+            </div>
+            <div class="dropdowns-foots">
+                清空通知
+            </div>
+            <!-- <Empy type='Flag' text='你还没有新的代办事项' /> -->
+        </el-tab-pane>
+  </el-tabs>
+</template>
+
+<script>
+// 通知 每一栏
+import Drop from './drop'
+// 消息 每一栏
+import NewsBox from './newsBox'
+// 代办 每一栏
+import Matter from './matter'
+// 清空图标
+import Clear from '@/assets/icon/clear.svg'
+
+// 空
+import Empy from './empy'
+
+export default {
+    data() {
+      return {
+        activeName: 'first',
+        dropOff: false
+      };
+    },
+    components:{
+        Drop,
+        Clear,
+        NewsBox,
+        Empy,
+        Matter
+    },
+    methods: {
+      handleClick(tab, event) {
+        // console.log(tab, event);
+      }
+    }
+}
+</script>
+
+<style>
+.el-tabs__nav-scroll{
+    display: flex;
+    justify-content: center;
+}
+.el-tabs__nav{
+    /* width: 320px!important; */
+    display: flex!important;
+    justify-content: center !important;
+}
+.el-tabs__header{
+    margin-bottom: 0!important;
+}
+.dropdowns-dropBox{
+  width: 100%;
+  /* min-height: 330px;
+  max-height: 450px; */
+  max-height: 450px;
+  overflow: hidden;
+  position: relative;
+}
+.dropdowns-list-box{
+  max-height: 450px;
+  overflow-x: hidden;
+  overflow-y: auto;
+  -ms-overflow-style: none; 
+  overflow: '-moz-scrollbars-none';
+  scrollbar-width: none;  /*  火狐   */
+  position: relative;
+  padding-bottom: 40px;
+  box-sizing: border-box;
+}
+.dropdowns-list-box::-webkit-scrollbar {
+    display: none;  /*  Chrome  */
+    width: 0 !important ; /*  Chrome  */
+}
+.dropdowns-list-box .drop:nth-last-child(1){
+  border-bottom: transparent;
+}
+.dropdowns-dropBox-scroll{
+  width: 300px;
+  /* height: 328px; */
+  
+}
+.happy-scroll-container{
+  width: 300px !important;
+}
+.happy-scroll-container .happy-scroll-content{
+  /* padding-bottom: 38px !important; */
+  box-sizing: border-box !important;
+  width: 300px !important;
+}
+.happy-scroll-container{
+  height: 290px !important; 
+}
+.dropdowns-more{
+  width: 100%;
+  height: 30px;
+  color: #2D8CF0;
+  font-size: 14px;
+  text-align: center;
+  line-height: 30px;
+ 
+}
+.dropdowns-foots{
+  width: 100%;
+  height: 38px;
+  background: #f7f7f7;
+  font-size: 14px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  color: #515A6E;
+  border-top: 1px solid #dcdfe6;
+  position: absolute;
+  bottom: -2px;
+  left: 0;
+}
+.dropdowns-foots-iconsClear{
+  width: 16px;
+  height: 16px;
+  margin-right: 5px;
+  color: #515A6E;
+  fill: currentColor;
+}
+.dropdowns-foots:hover{
+  /* color: #2AB4FB!important; */
+  background: #E8F6FD;
+}
+.disableds{
+  pointer-events: none;
+}
+</style>

+ 141 - 0
src/components/Dropdown/matter.vue

@@ -0,0 +1,141 @@
+<template>
+    <div class="drop">
+        <div class="drop-right">
+            <p>{{text}}</p>
+            <p>{{time}}</p>
+        </div>
+        <div class="drop-left">
+            <el-link v-if="type == 'primary'"  class="drop-left-btns drop-left-btns-primary" type="primary" :underline="false">进行中</el-link>
+            <el-link v-if="type == 'success'"  class="drop-left-btns drop-left-btns-success" type="success" :underline="false">完成</el-link>
+            <el-link v-if="type == 'warning'"  class="drop-left-btns drop-left-btns-warning" type="warning" :underline="false">即将到期</el-link>
+            <el-link v-if="type == 'danger'"  class="drop-left-btns drop-left-btns-danger" type="danger" :underline="false">未完成</el-link>
+            <el-link v-if="type == 'info'" class="drop-left-btns drop-left-btns-info" type="info" :underline="false">未开始</el-link>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    props:{
+        text:{
+            type: String,
+            default: 'Zhuye',
+            required: true
+        },
+        time:{
+            type: String,
+            required: true
+        },
+        type:{
+            type: String,
+            default: 'info',
+            validator: function (value) {
+                // 这个值必须匹配下列字符串中的一个
+                return ['info', 'danger','warning','success','primary'].indexOf(value) !== -1
+            }
+        },
+    }
+}
+</script>
+
+<style scoped>
+.drop{
+    width: 300px;
+    min-height: 65px !important;
+    max-height: 87px !important;
+    border-bottom: 1px solid #dcdfe6;
+    padding: 12px 24px;
+    box-sizing: border-box;
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+
+}
+.drop:hover{
+    background: #E2EFFD;
+}
+.drop:hover img{
+    transform: scale(1.5) rotate(360deg);
+    opacity: 1;
+}
+.drop-left{
+    width: 80px;
+    height: 32px;
+    border-radius: 16px;
+    margin-right: 10px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    overflow: hidden;
+}
+.drop-left img{
+    width: 32px;
+    height: 32px;
+    transition: all 0.5s;
+}
+.drop-left-icon{
+    width: 20px;
+    height: 20px;
+    fill: currentColor; 
+    opacity: 0.9;
+    transition: all 0.5s;
+}
+.drop-left-btns{
+    height: 20px;
+    padding: 0 10px;
+    font-size: 12px;
+    border-radius: 2px;
+}
+.drop-left-btns-primary{
+    background: #E8F6FD;
+    border: 1px solid #91D5FF;
+}
+.drop-left-btns-success{
+    background: #F8FDF6;
+    border: 1px solid #A2FC76;
+}
+.drop-left-btns-warning{
+    background: #FDF9F4;
+    border: 1px solid #FDC673;
+}
+.drop-left-btns-danger{
+    background: #FEF5F5;
+    border: 1px solid #FCBEBE;
+}
+.drop-left-btns-info{
+    background: #FCFCFD;
+    border: 1px solid #CDCDCD;
+}
+.drop-right{
+    flex: 1;
+    display: flex;
+    align-items: stretch;
+    flex-wrap: wrap;
+}
+.drop-right p{
+    width: 100%;
+    
+}
+.drop-right p:nth-child(1){
+    font-size: 14px;
+    font-weight: 400;
+    line-height: 22px;
+    color: #515a6e;
+    margin-bottom: 5px;
+    max-height: 44px;
+    min-height: 22px;
+    text-overflow: -o-ellipsis-lastline;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    display: -webkit-box;
+    -webkit-line-clamp: 2;
+    -webkit-box-orient: vertical;
+}
+.drop-right p:nth-child(2){
+    font-size: 12px;
+    color: #808695;
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+
+</style>

+ 115 - 0
src/components/Dropdown/newsBox.vue

@@ -0,0 +1,115 @@
+<template>
+    <div class="drop">
+        <div class="drop-left">
+            <img src="http://public.nodebook.top/20200319164136.jpg" />
+        </div>
+        <div class="drop-right">
+            <p>{{text}}</p>
+            <p>{{time}}</p>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    props:{
+        text:{
+            type: String,
+            default: 'Zhuye',
+            required: true
+        },
+        time:{
+            type: String,
+            required: true
+        },
+        image:{
+            type: String,
+            default: 'http://public.nodebook.top/20200319164136.jpg',
+            validator: function (value) {
+                let colorImage = /^https?:\/\/(.+\/)+.+(\.(gif|png|jpg|jpeg|webp|svg|psd|bmp|tif))$/i
+                // 必须匹配一个颜色的正则
+                if(colorImage.test(value)){
+                    return true
+                }
+                return false;
+            }
+        }
+    }
+}
+</script>
+
+<style scoped>
+.drop{
+    width: 300px;
+    min-height: 65px !important;
+    max-height: 87px !important;
+    border-bottom: 1px solid #dcdfe6;
+    padding: 12px 24px;
+    box-sizing: border-box;
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+
+}
+.drop:hover{
+    background: #E2EFFD;
+}
+.drop:hover img{
+    transform: scale(1.5) rotate(360deg);
+    opacity: 1;
+}
+.drop-left{
+    width: 32px;
+    height: 32px;
+    background: burlywood;
+    border-radius: 16px;
+    margin-right: 10px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    overflow: hidden;
+}
+.drop-left img{
+    width: 32px;
+    height: 32px;
+    transition: all 0.5s;
+}
+.drop-left-icon{
+    width: 20px;
+    height: 20px;
+    fill: currentColor; 
+    opacity: 0.9;
+    transition: all 0.5s;
+}
+.drop-right{
+    flex: 1;
+    display: flex;
+    align-items: stretch;
+    flex-wrap: wrap;
+}
+.drop-right p{
+    width: 100%;
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+.drop-right p:nth-child(1){
+    font-size: 14px;
+    font-weight: 400;
+    line-height: 22px;
+    color: #515a6e;
+    margin-bottom: 5px;
+    max-height: 44px;
+    min-height: 22px;
+    text-overflow: -o-ellipsis-lastline;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    display: -webkit-box;
+    -webkit-line-clamp: 2;
+    -webkit-box-orient: vertical;
+}
+.drop-right p:nth-child(2){
+    font-size: 12px;
+    color: #808695;
+}
+
+</style>

+ 378 - 0
src/components/Headers/Headers.vue

@@ -0,0 +1,378 @@
+<template>
+    <div class="headers">
+        <div class="headers-left">
+            <div class="headers-left-box" :class="asideShow === false ? 'headers-left-active' : ''" @click="targetIcon">
+                <i class="el-icon-s-fold "></i>
+            </div>
+            <Breadcrumb />
+        </div>
+        <div class="headers-right">
+            <div class="headers-right-left">
+                <!-- <el-tooltip class="item" effect="dark" content="源码" placement="bottom">
+                    <github2 class="headers-right-left-githubIcon" @click="goGithub" />
+                </el-tooltip> -->
+                <el-tooltip class="item" effect="dark" :content="isFullscreen ? '取消全屏' : '全屏'" placement="bottom">
+                    <!-- <i :class="isFullscreen ? 'el-icon-full-screen head-screen-news' : 'el-icon-rank head-screen'" @click="buttoncli"></i> -->
+                    <reduction v-if="isFullscreen" class="headers-right-left-screenIcon" @click="buttoncli" />
+                    <screen v-else class="headers-right-left-screenIcon" @click="buttoncli" />
+                </el-tooltip>
+                <el-tooltip class="item" style="margin: 0 20px 0 10px; color: #171700" effect="dark" content="主题" placement="bottom">
+                    <i class="el-icon-picture-outline-round" @click="theme = true"></i>
+                </el-tooltip>
+                <!-- <el-tooltip class="item" effect="dark" :disabled='dropShow' content="有5条未读消息" placement="bottom" @mouseover="dropShow = !dropShow"> -->
+                    <el-badge is-dot class="item">
+                        <i class="el-icon-bell head-news-icon" @mouseover.self="dropShowBtn" @mouseout.self="dropHideBtn"></i>
+                    </el-badge>
+                <!-- </el-tooltip> -->
+                <!-- 通知栏 -->
+                <div class="header-right-dropdown" @mouseover="dropdownBtn" @mouseout="dropShow = false">
+                    <el-collapse-transition>
+                        <Dropdowns v-show="dropShow" />
+                    </el-collapse-transition>
+                </div>
+            </div>
+            <div class="headers-right-right">
+                <div class="block"><el-avatar shape="square" size="large" :src="squareUrl"></el-avatar></div>
+                <el-dropdown size="medium" @command="handleCommand">
+                    <span class="el-dropdown-link">
+                        admin<i class="el-icon-arrow-down el-icon--right"></i>
+                    </span>
+                    <el-dropdown-menu slot="dropdown">
+                        <!-- <el-dropdown-item command="github">项目仓库</el-dropdown-item> -->
+                        <el-dropdown-item divided command="quit">退出登录</el-dropdown-item>
+                    </el-dropdown-menu>
+                </el-dropdown>
+            </div>
+        </div>
+        <el-drawer
+            :with-header="false"
+            :visible.sync="theme"
+            direction="rtl"
+            size='400px'
+            class="theme"
+            >
+            <div class="theme-title">配色方案</div>
+            <div class="theme-title-box">
+                <div class="theme-title-box-list" v-for="(item,index) in themeColor" :key="index" @click="targetThemeIndex(index)" :class="themeIndex === index ? 'theme-active' : ''">
+                    <div class="theme-title-box-list-left" :style="item.aside"></div>
+                    <div class="theme-title-box-list-right">
+                        <div class="theme-title-box-list-right-top" :style="item.header"></div>
+                        <div class="theme-title-box-list-right-bottom" :style="item.container"></div>
+                    </div>
+                </div>
+            </div>
+        </el-drawer>
+    </div>
+</template>
+
+
+<script>
+// 全屏组件
+import screenfull from 'screenfull'
+
+// 面包屑
+import Breadcrumb from '../Breadcrumb/Breadcrumb2'
+
+// 通知栏组件
+import Dropdowns from '../Dropdown/index'
+
+import github2 from '../../assets/icon/github2.svg' //github
+import screen from '../../assets/icon/screen.svg'  //全屏
+import reduction from '../../assets/icon/reduction.svg' //还原
+
+export default {
+    props:{
+        asideShow: {
+            type: Boolean,
+            default: true
+        },
+        themeColor: {
+            type: Array,
+            default: true
+        },
+        themeIndex: {
+            type: Number,
+            default: true
+        }
+    },
+    data(){
+        return {
+            squareUrl: "https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png",
+            isFullscreen: false,
+            dropShow: false , // 是否现实通知栏
+            setTime: null , //定时器
+            theme: false // 主题 开关
+        }
+    },
+    components:{
+        Breadcrumb,
+        Dropdowns,
+        github2,
+        screen,
+        reduction
+    },
+    methods:{
+        // 自定义 切换 侧边栏 事件
+        targetIcon(){
+            this.$emit('targetIcon',!this.asideShow)
+        },
+        // 全屏
+        buttoncli(){
+				// if (!screenfull.enabled) { // 如果不允许进入全屏,发出不允许提示
+                //     this.$message({
+                //         message: '不支持全屏',
+                //         type: 'warning'
+                //     })
+                //     return false
+                // }
+                screenfull.toggle()
+                this.checkFull()
+        },
+        // 监控屏幕变化
+        checkFull() {
+            var isFull = document.fullscreenEnabled || window.fullScreen || document.webkitIsFullScreen || document.msFullscreenEnabled;
+            // to fix : false || undefined == undefined
+            // 是否全屏判断
+            this.isFullscreen = !this.isFullscreen;
+            if(this.isFullscreen){
+                this.$message({
+                    message: '全屏啦',
+                    type: 'success'
+                })
+            }else{
+                this.$message({
+                        message: '取消全屏',
+                        type: 'warning'
+                    })
+            }
+           
+            if (isFull === undefined) {
+                isFull = false;
+            }
+            return isFull;
+        },
+        // 用户名 下拉菜单
+        handleCommand(command){
+          
+            switch(command){
+                case 'github':
+                   
+                    window.open('https://github.com/cgq001/admin-menu/tree/2.0')
+                break;
+                case 'quit':
+                    let src = this.$store.dispatch('user/resetToken')
+                    this.$router.replace('/login')
+                break;
+
+            }
+        },
+        // 退出登陆
+        quits(){
+            this.$cookie.remove("token");
+            // this.$store.dispatch('user/resetToken')
+        },
+        // 展开通知
+        dropShowBtn(){
+            clearTimeout(this.setTime)
+            this.dropShow = true
+        },
+        // 收起通知
+        dropHideBtn(){
+            let This = this
+            
+            this.setTime = setTimeout(function(){
+                This.dropShow = false;
+            },1000)
+        },
+        // 鼠标移入 通知栏
+        dropdownBtn(){
+            clearTimeout(this.setTime)
+            this.dropShow = true
+        },
+        // 选取配色方案
+        targetThemeIndex(index){
+            this.$emit('targetThemeIndex',index)
+        },
+        // 去github
+        goGithub(){
+            window.open('https://github.com/cgq001/admin-menu/tree/2.0')
+        }
+    },
+    mounted() {
+        // 浏览器窗口改变事件
+        this.isFullscreen = document.body.scrollHeight === window.screen.height
+    }
+}
+</script>
+
+<style scoped>
+.headers{
+    width: 100%;
+    height: 100%;
+    display: flex;
+    justify-content: space-between;
+}
+.headers-left{
+    display: flex;
+    justify-content: flex-start;
+}
+.headers-left-box{
+    transition: all 0.5s;
+    transform-origin: center center;
+    width: 20px;
+    height: 100%;
+    margin-right: 15px;
+}
+.headers-left-active{
+    transform: rotate(180deg);
+}
+.el-icon-s-fold{
+    width: 20px;
+    height: 100%;
+    line-height: 50px;
+    font-size: 20px;
+    cursor: pointer;
+    
+}
+.el-breadcrumb{
+    line-height: 50px;
+}
+.headers-right{
+    /* width: 200px; */
+    height: 100%;
+    /* background: orchid; */
+    display: flex;
+    justify-content: space-around;
+}
+.headers-right-left{
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+    margin-right: 30px;
+    font-size: 22px;
+    cursor: pointer;
+    position: relative;
+}
+.headers-right-left-screenIcon{
+    width: 18px;
+    height: 18px;
+    margin-right: 10px;
+    fill: currentColor; 
+    color: #413A3F;
+}
+.headers-right-left-githubIcon{
+    width: 20px;
+    height: 20px;
+    margin-right: 20px;
+    fill: currentColor; 
+    color: #413A3F;
+}
+.header-right-dropdown{
+    width: 300px;
+    height: auto;
+    position: absolute;
+    right: 0;
+    top: 60px;
+    z-index: 2;
+    background: #ffffff;
+    /* padding: 5px 0; */
+    box-sizing: border-box;
+    border-radius: 4px;
+    box-shadow: 0 1px 6px rgba(0,0,0,.2);
+    overflow: hidden;
+}
+/* .head-news-icon{
+    
+} */
+.head-screen{
+    margin-right: 15px;
+    transform: rotate(45deg);
+}
+.head-screen-news{
+    margin-right: 15px;
+}
+.headers-right-right{
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+    color: #666666;
+}
+.block{
+    margin-right: 15px;
+}
+.el-dropdown-link{
+    cursor: pointer;
+}
+.focusing{
+    border: none !important;
+}
+/* 主题 */
+.theme{
+    height: 100vh;
+    overflow: hidden;
+}
+.el-drawer__body{
+    height: 100vh !important;
+    overflow: hidden;
+}
+.theme-title{
+    width: 100%;
+    height: 50px;
+    line-height: 50px;
+    font-size: 16px;
+    font-weight: bold;
+    padding: 0 15px;
+    border-bottom: 1px solid #dcdfe6;
+}
+.theme-title-box{
+    padding: 10px;
+    box-sizing: border-box;
+    width: 100%;
+    display: flex;
+    justify-content: space-between;
+    flex-wrap: wrap;
+    height: calc(100vh - 51px);
+    overflow-x: hidden;
+    overflow-y: auto;
+    -ms-overflow-style: none; 
+    overflow: '-moz-scrollbars-none';
+    scrollbar-width: none;  /*  火狐   */
+    background: #F5F7F9;
+}
+.theme-title-box::-webkit-scrollbar {
+    display: none;  /*  Chrome  */
+    width: 0 !important ; /*  Chrome  */
+}
+.theme-title-box-list{
+    width: 180px;
+    height: 150px;
+    display: flex;
+    padding: 10px;
+    box-sizing: border-box;
+    background: #999999;
+    border-radius: 5px;
+    cursor: pointer;
+    margin-bottom: 10px;
+    border: 5px solid transparent;
+}
+.theme-title-box-list-left{
+    width: 30px;
+    height: 120px;
+}
+.theme-title-box-list-right{
+    flex: 1;
+    height: 160px;
+}
+.theme-title-box-list-right-top{
+    width: 100%;
+    height: 20px;
+    background: #ffffff;
+}
+.theme-title-box-list-right-bottom{
+    width: 100%;
+    height: 100px;
+}
+.theme-active{
+    border: 5px solid #05DA89;
+}
+</style>

+ 97 - 0
src/components/Home/InformationList.vue

@@ -0,0 +1,97 @@
+<template>
+    <div class="Information">
+        <div class="Information-title">
+            <el-button type="danger"  size="mini" >删除</el-button>
+            <el-button type="primary"  size="mini" >标为已读</el-button>
+        </div>
+        <div class="Information-table">
+            <el-table
+                ref="multipleTable"
+                :data="tableData"
+                tooltip-effect="dark"
+                style="width: 100%"
+                @selection-change="handleSelectionChange">
+                <el-table-column
+                type="selection"
+                width="55">
+                </el-table-column>
+                <el-table-column
+                prop="name"
+                label="姓名"
+                width="120">
+                </el-table-column>
+                <el-table-column
+                prop="address"
+                label="地址"
+                show-overflow-tooltip>
+                </el-table-column>
+                <el-table-column
+                label="日期"
+                width="120">
+                <template slot-scope="scope">{{ scope.row.date }}</template>
+                </el-table-column>
+            </el-table>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    data(){
+        return {
+            tableData: [{
+                date: '2016-05-03',
+                name: '王小虎',
+                address: '上海市普陀区金沙江路 1518 弄'
+                }, {
+                date: '2016-05-02',
+                name: '王小虎',
+                address: '上海市普陀区金沙江路 1518 弄'
+                }, {
+                date: '2016-05-04',
+                name: '王小虎',
+                address: '上海市普陀区金沙江路 1518 弄'
+                }, {
+                date: '2016-05-01',
+                name: '王小虎',
+                address: '上海市普陀区金沙江路 1518 弄'
+                }, {
+                date: '2016-05-08',
+                name: '王小虎',
+                address: '上海市普陀区金沙江路 1518 弄'
+                }, {
+                date: '2016-05-06',
+                name: '王小虎',
+                address: '上海市普陀区金沙江路 1518 弄'
+                }, {
+                date: '2016-05-07',
+                name: '王小虎',
+                address: '上海市普陀区金沙江路 1518 弄'
+            }],
+            multipleSelection: []
+        }
+    },
+    methods: {
+      toggleSelection(rows) {
+        if (rows) {
+          rows.forEach(row => {
+            this.$refs.multipleTable.toggleRowSelection(row);
+          });
+        } else {
+          this.$refs.multipleTable.clearSelection();
+        }
+      },
+      handleSelectionChange(val) {
+        this.multipleSelection = val;
+      }
+    }
+}
+</script>
+
+<style scoped>
+.Information-title{
+    width: 100%;
+    height: auto;
+    margin-bottom: 10px;
+}
+</style>

+ 145 - 0
src/components/Index/colleague.vue

@@ -0,0 +1,145 @@
+<template>
+    <div class="colleague" >
+        <div class="colleague-list" v-for="item in personList" :key="item.name">
+            <div class="colleague-list-left">
+                <img src="http://public.nodebook.top/fd123a3921e910809fba9da0101bf8f6.jpg" />
+            </div>
+            <div class="colleague-list-centent">
+                <p>{{item.name}}</p>
+                <p>{{item.position}}</p>
+            </div>
+            <div class="colleague-list-right">
+                <span v-if="item.onLine" class="colleague-list-right-online">在线</span>
+                <span v-else class="colleague-list-right-outline">;离线</span>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    data(){
+        return {
+            personList:[
+                {
+                    name: '王小明',
+                    position: '前端开发',
+                    onLine: true
+                },
+                {
+                    name: '李小明',
+                    position: 'Java',
+                    onLine: true
+                },
+                {
+                    name: '张小明',
+                    position: 'PHP',
+                    onLine: false
+                },
+                {
+                    name: '宋小明',
+                    position: 'python',
+                    onLine: true
+                },
+                {
+                    name: '曹小明',
+                    position: 'golang',
+                    onLine: false
+                },
+                {
+                    name: '靳小明',
+                    position: 'IOS',
+                    onLine: true
+                },
+                {
+                    name: '卫小明',
+                    position: '安卓',
+                    onLine: true
+                }
+            ]
+        }
+    }
+}
+</script>
+
+<style scoped>
+.colleague{
+    width: 100%;
+    max-height: 355px;
+    overflow-x: hidden;
+    overflow-y: auto;
+    -ms-overflow-style: none; 
+    overflow: '-moz-scrollbars-none';
+    scrollbar-width: none;  /*  火狐   */
+}
+.colleague::-webkit-scrollbar {
+    display: none;  /*  Chrome  */
+    width: 0 !important ; /*  Chrome  */
+}
+.colleague .colleague-list:nth-last-child(1){
+    border-color: transparent;
+}
+.colleague-list{
+    width: 100%;
+    height: 71px;
+    border-bottom: 1px solid #dcdfe6;
+    padding: 10px 0;
+    box-sizing: border-box;
+    display: flex;
+    justify-content: space-between;
+    cursor: pointer;
+}
+.colleague-list:hover{
+    background: #DBFEFB;
+}
+.colleague-list-left,.colleague-list-left img{
+    width: 50px;
+    height: 50px;
+    border-radius: 10px;
+    overflow: hidden;
+}
+.colleague-list-centent{
+    flex: 1;
+    padding-left: 15px;
+    box-sizing: border-box;
+    display: flex;
+    flex-direction:column;
+    justify-content: space-around;
+    
+}
+.colleague-list-centent p:nth-child(1){
+    font-size: 14px;
+    font-weight: bold;
+}
+.colleague-list-centent p:nth-child(2){
+    font-size: 12px;
+    color: #999999;
+}
+.colleague-list-right{
+    width: 100px;
+    height: 50px;
+    padding-top: 13px;
+    display: flex;
+    justify-content: flex-end;
+}
+.colleague-list-right span{
+    display: inline-block;
+    width: 52px;
+    height: 24px;
+    text-align: center;
+    line-height: 26px;
+    border-radius: 2px;
+    border: 1px solid;
+    font-size: 12px;
+}
+.colleague-list-right-online{
+    border-color: #0D9AFF;
+    color: #0D9AFF;
+    background: #DEEFFB;
+}
+.colleague-list-right-outline{
+    border-color: #FD41F0;
+    color: #FD41F0;
+    background: #FEEDFD;
+}
+</style>

+ 150 - 0
src/components/Index/dynamicBox.vue

@@ -0,0 +1,150 @@
+<template>
+    <div class="dynamic">
+        <vue-seamless-scroll :data='dynamicList' class="dynamic-warp">
+            <div class="dynamic-list" v-for="item in dynamicList" :key="item.name">
+                <div class="dynamic-list-left">
+                    <img src="http://public.nodebook.top/fd123a3921e910809fba9da0101bf8f6.jpg" />
+                </div>
+                <div class="dynamic-list-right">
+                    <p class="dynamic-list-right-top">
+                        <span>{{item.name}}</span>
+                        <span>{{item.type}}</span>
+                        <span>{{item.msg}}</span>
+                    </p>
+                    <p class="dynamic-list-right-bottom">
+                        {{item.time}}
+                    </p>
+                </div>
+            </div>
+        </vue-seamless-scroll>
+    </div>
+</template>
+
+<script>
+// 滚动样式详见: https://chenxuan1993.gitee.io/component-document/index_prod#/component/seamless-default
+export default {
+    data(){
+        return {
+            dynamicList:[
+                {
+                    name: '小张',
+                    type: '订购了',
+                    msg: '紫砂壶',
+                    time: '12-10 10:12'
+                },
+                {
+                    name: '小李',
+                    type: '订购了',
+                    msg: '绿茶',
+                    time: '12-10 10:12'
+                },
+                {
+                    name: '小王',
+                    type: '订购了',
+                    msg: '清茶',
+                    time: '12-10 10:12'
+                },
+                {
+                    name: '小林',
+                    type: '订购了',
+                    msg: '茉莉花茶',
+                    time: '12-10 10:12'
+                },
+                {
+                    name: '小时',
+                    type: '订购了',
+                    msg: '豆腐',
+                    time: '12-10 10:12'
+                },
+                {
+                    name: '小七',
+                    type: '订购了',
+                    msg: '萝卜',
+                    time: '12-10 10:12'
+                },
+                {
+                    name: '小齐',
+                    type: '订购了',
+                    msg: '青菜',
+                    time: '12-10 10:12'
+                },
+                {
+                    name: '小新',
+                    type: '订购了',
+                    msg: '新茶',
+                    time: '12-10 10:12'
+                },
+                {
+                    name: '小金',
+                    type: '订购了',
+                    msg: '毛尖',
+                    time: '12-10 10:12'
+                },
+                {
+                    name: '小毛',
+                    type: '订购了',
+                    msg: '红茶',
+                    time: '12-10 10:12'
+                }
+            ]
+        }
+    }
+}
+</script>
+
+<style scoped>
+.dynamic{
+    width: 100%;
+    height: auto;
+}
+.dynamic-warp{
+    height: 651px;
+    overflow: hidden;
+}
+.dynamic-list{
+    width: 100%;
+    height: 93px;
+    padding: 25px 0;
+    border-bottom: 1px solid #dcdfe6;
+    box-sizing: border-box;
+    display: flex;
+    justify-content: space-between;
+    cursor: pointer;
+}
+.dynamic-list:hover{
+    background: #DBFEFB;
+}
+.dynamic-list-left,.dynamic-list-left img{
+    width: 42px;
+    height: 42px;
+    border-radius: 21px;
+    overflow: hidden;
+    margin-right: 25px;
+}
+.dynamic-list-right{
+    flex: 1;
+    height: 42px;
+    display: flex;
+    justify-content: space-between;
+    flex-direction: column;
+    
+}
+.dynamic-list-right .dynamic-list-right-top{
+    font-size: 14px;
+}
+.dynamic-list-right-top span:nth-child(1){
+    color: #3B3C3C;
+    margin-right: 15px;
+}
+.dynamic-list-right-top span:nth-child(2){
+    color: #7C7E81;
+    margin-right: 5px;
+}
+.dynamic-list-right-top span:nth-child(3){
+    color: #2E93FD;
+}
+.dynamic-list-right-bottom{
+    color: #999999;
+    font-size: 12px;
+}
+</style>

+ 135 - 0
src/components/Index/fast.vue

@@ -0,0 +1,135 @@
+<template>
+    <div class="Fast">
+        <div class="Fast-list">
+            <div class="Fast-list-top">
+                <ship class="Fast-list-top-icon icon-ship" />
+            </div>
+            <div class="Fast-list-bottom">
+                待发货
+            </div>
+        </div>
+        <div class="Fast-list">
+            <div class="Fast-list-top">
+                <refund class="Fast-list-top-icon icon-refund" />
+            </div>
+            <div class="Fast-list-bottom">
+                待退款
+            </div>
+        </div>
+        <div class="Fast-list">
+            <div class="Fast-list-top">
+                <shelves class="Fast-list-top-icon icon-shelves" />
+            </div>
+            <div class="Fast-list-bottom">
+                商品上架
+            </div>
+        </div>
+        <div class="Fast-list">
+            <div class="Fast-list-top">
+                <feedback class="Fast-list-top-icon icon-feedback"  />
+            </div>
+            <div class="Fast-list-bottom">
+                意见反馈
+            </div>
+        </div>
+        <div class="Fast-list">
+            <div class="Fast-list-top">
+                <finance class="Fast-list-top-icon icon-finance" />
+            </div>
+            <div class="Fast-list-bottom">
+                财务
+            </div>
+        </div>
+        <div class="Fast-list">
+            <div class="Fast-list-top">
+                <analysis class="Fast-list-top-icon icon-analysis" />
+            </div>
+            <div class="Fast-list-bottom">
+                数据分析
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import ship from '@/assets/icon/ship.svg'
+import refund from '@/assets/icon/refund.svg'
+import feedback from '@/assets/icon/feedback.svg'
+import shelves from '@/assets/icon/shelves.svg'
+import finance from '@/assets/icon/finance.svg'
+import analysis from '@/assets/icon/analysis.svg'
+export default {
+    components:{
+        ship,
+        refund,
+        feedback,
+        shelves,
+        finance,
+        analysis
+    }
+}
+</script>
+<style scoped>
+.Fast{
+    width: 100%;
+    height: auto;
+    display: flex;
+    justify-content: space-between;
+    flex-wrap: wrap;
+}
+.Fast-list{
+    width: 33%;
+    height: 56px;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-around;
+    cursor: pointer;
+    margin-bottom: 15px;
+    border-radius: 5px;
+}
+.Fast-list:hover{
+    background: #16B3FD;
+    color: #ffffff;
+
+}
+.Fast-list:hover .Fast-list-top-icon{
+    color: #ffffff !important;
+}
+.Fast-list:hover .Fast-list-bottom{
+    color: #ffffff !important;
+}
+.Fast-list-top{
+    width: 100%;
+    display: flex;
+    justify-content: center;
+}
+.Fast-list-top-icon{
+    width: 20px;
+    height: 20px;
+    fill: currentColor;
+}
+.Fast-list-bottom{
+    font-size: 12px;
+    color: #3F495E;
+    text-align: center;
+}
+.icon-ship{
+    color: #18FD6C;
+}
+.icon-refund{
+    color: #F85E1F;
+}
+.icon-feedback{
+    font-weight: bolder;
+    color: #FE4B60;
+}
+.icon-shelves{
+    color: #18A2FD;
+}
+.icon-finance{
+   color: #09F8BA;   
+}
+.icon-analysis{
+    color: #952BFD;
+}
+</style>

+ 145 - 0
src/components/Index/project.vue

@@ -0,0 +1,145 @@
+<template>
+    <el-row :gutter="10" class="project">
+        <el-col :xs="12" :sm="12" :md="12" :lg="8" :xl="8">
+            <div class="project-list">
+                <div class="project-list-left">
+                    <uni class="project-list-left-icon" />
+                </div>
+                <div class="project-list-right">
+                    <count-to :startVal='startVal' :endVal='47' :duration='3000'></count-to>
+                    star
+                </div>
+            </div>
+        </el-col>
+        <el-col :xs="12" :sm="12" :md="12" :lg="8" :xl="8">
+            <div class="project-list">
+                <div class="project-list-left">
+                    <react class="project-list-left-icon" />
+                </div>
+                <div class="project-list-right">
+                    <count-to :startVal='startVal' :endVal='17' :duration='3000'></count-to>
+                    star
+                </div>
+            </div>
+        </el-col>
+        <el-col :xs="12" :sm="12" :md="12" :lg="8" :xl="8">
+            <div class="project-list">
+                <div class="project-list-left">
+                    <nodejs class="project-list-left-icon" />
+                </div>
+                <div class="project-list-right">
+                    <count-to :startVal='startVal' :endVal='10' :duration='3000'></count-to>
+                    star
+                </div>
+            </div>
+        </el-col>
+        <el-col :xs="12" :sm="12" :md="12" :lg="8" :xl="8">
+            <div class="project-list">
+                <div class="project-list-left">
+                    <vues class="project-list-left-icon" />
+                </div>
+                <div class="project-list-right">
+                    <count-to :startVal='startVal' :endVal='11' :duration='3000'></count-to>
+                    star
+                </div>
+            </div>
+        </el-col>
+        <el-col :xs="12" :sm="12" :md="12" :lg="8" :xl="8">
+            <div class="project-list">
+                <div class="project-list-left">
+                    <vues class="project-list-left-icon" />
+                </div>
+                <div class="project-list-right">
+                    <count-to :startVal='startVal' :endVal='7' :duration='3000'></count-to>
+                    star
+                </div>
+            </div>
+        </el-col>
+        <el-col :xs="12" :sm="12" :md="12" :lg="8" :xl="8">
+            <div class="project-list">
+                <div class="project-list-left">
+                    <apps class="project-list-left-icon" />
+                </div>
+                <div class="project-list-right">
+                    <count-to :startVal='startVal' :endVal='3' :duration='3000'></count-to>
+                    star
+                </div>
+            </div>
+        </el-col>
+    </el-row>
+</template>
+
+<script>
+import apps from '@/assets/icon/app.svg'
+import nodejs from '@/assets/icon/nodejs.svg'
+import react from '@/assets/icon/react.svg'
+import vues from '@/assets/icon/vue.svg'
+import uni from '@/assets/icon/u.svg'
+import countTo from 'vue-count-to';
+export default {
+    data(){
+        return {
+            startVal: 0,
+            endVal: 10
+        }
+    },
+    components:{
+        apps,
+        nodejs,
+        react,
+        vues,
+        uni,
+        countTo
+    }
+}
+</script>
+
+<style scoped>
+.project{
+    width: 100%;
+    height: auto;
+}
+.project-list{
+    width: 100%;
+    height: 108px;
+    /* background: #f7f7f7; */
+    border-radius: 5px;
+    cursor: pointer;
+    padding: 14px;
+    box-sizing: border-box;
+    background: url('../../assets/image/vue.png');
+    background-size: 100% 100%;
+    display: flex;
+    justify-content: space-between;
+    margin-bottom: 15px;
+}
+.project-list-left{
+    padding: 16px;
+    box-sizing: border-box;
+    width: 80px;
+    height: 80px;
+    border-radius: 5px;
+}
+.project-list-left:hover{
+    background: #E84D67;
+}
+.project-list-left:hover .project-list-left-icon{
+    color: #ffffff;
+}
+.project-list-left-icon{
+    width: 48px;
+    height: 48px;
+    fill: currentColor; 
+    color: #ffffff;
+    
+}
+.project-list-right{
+    flex: 1;
+    color: #EA4E68;
+    font-weight: bolder;
+    font-size: 30px;
+    line-height: 80px;
+    text-align: right;
+    color: #ffffff;
+}
+</style>

+ 31 - 0
src/components/Sidebar/Item.vue

@@ -0,0 +1,31 @@
+<script>
+export default {
+    name: "MenuItem",
+    functional: true,
+    props:{
+        icon: {
+            type: String,
+            default: ''
+        },
+        title: {
+            type: String,
+            default: ''
+        }
+    },
+    render(h, context){
+        const { icon, title } = context.props
+        const vnodes = []
+      
+        if(icon){
+            // vnodes.push(<svg-icon icon-class={icon} />)
+            vnodes.push(<i class={icon} style={{color: '#ffffff'}}></i>)
+        }
+        if(title){
+  
+            vnodes.push(<span slot='title'>{title}</span>)
+        }
+          
+        return vnodes
+    }
+}
+</script>

+ 113 - 0
src/components/Sidebar/SidebarItem.vue

@@ -0,0 +1,113 @@
+<template>
+    <div v-if="!item.hidden" class="menu-wrapper">
+        <!-- 仅有一个可显示的子路由,并且没有孙子路由 && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && item.alwaysShow-->
+        <template v-if="hasOneShowingChild(item.children,item)">
+            <router-link v-if="onlyOneChild.meta && !onlyOneChild.meta.hidden" :to="resolvePath(onlyOneChild.path)">
+                <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown' : isNest }">
+                    <item :icon="onlyOneChild.meta.icon || (item.meta && item.meta.icon)" :title="onlyOneChild.meta.title" />
+                </el-menu-item>
+            </router-link>
+        </template>
+        <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
+            <template v-slot:title>
+                <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
+            </template>
+            <sidebar-item
+                v-for="child in item.children"
+                :key="child.path"
+                :is-nest='true'
+                :item='child'
+                :base-path="resolvePath(child.path)"
+                class="nest-menu"
+                />
+        </el-submenu>
+    </div>
+</template>
+
+<script>
+import path from 'path'
+import Item from './Item'
+
+export default {
+    name: "SidebarItem",
+    components: { Item },
+    props: {
+        item: {
+            type: Object,
+            required: true
+        },
+        isNest: {
+            type: Boolean,
+            required: false
+        },
+        basePath: {
+            type: String,
+            default: ''
+        }
+    },
+    data(){
+        this.onlyOneChild = null
+        return {
+            
+        }
+    },
+    mounted(){
+        // console.log(this.item)
+    },
+    methods:{
+        hasOneShowingChild(children = [],parent){
+           
+            const showingChildren = children.filter(item =>{
+                if(item.hidden){
+                    return false
+                } else {
+                    // 如果只有一个子菜单时设置
+                    this.onlyOneChild = item
+                    return true
+                }
+            })
+           
+            // 当只有一个子路由,子路由默认展示
+            if(showingChildren.length === 1){
+                return true
+            }
+            // 没有子路由则显示父路由
+            if(showingChildren.length === 0){
+                this.onlyOneChild = {...parent, path: '', noShowingChildren: true }
+                return true
+            }
+            //  console.log(this.onlyOneChild)
+            return false
+        },
+        resolvePath(routePath){
+            return path.resolve(this.basePath, routePath)
+        }
+    }    
+}
+</script>
+
+<style>
+.el-menu-item.is-active {
+    background: #1A86EE !important;
+}
+/* .el-submenu .el-menu-item{
+    height: 40px !important;
+    line-height: 40px !important;
+    margin: 2px 0 3px !important;
+}
+.el-menu-item{
+    height: 40px !important;
+    line-height: 40px !important;
+    margin: 2px 0 3px !important;
+}
+.el-submenu{
+    height: 40px !important;
+    line-height: 40px !important;
+    margin: 2px 0 3px !important;
+}
+.el-submenu__title{
+    height: 40px !important;
+    line-height: 40px !important;
+    margin: 2px 0 3px !important;
+} */
+</style>

+ 91 - 0
src/components/Sidebar/index.vue

@@ -0,0 +1,91 @@
+<template>
+  <div class="sidebar">
+    <div class="sidebar-title">后台管理系统</div>
+    <div class="sidebar-box">
+      <el-menu
+        class="el-menu-vertical-demo"
+        :collapse="false"
+        :default-active="activeMenu"
+        background-color="transparent"
+        :text-color="variables.menuText"
+        :unique-opened="false"
+        :active-text-color="variables.menuActiveText"
+        :collapse-transition="false"
+        mode="vertical"
+      >
+        <SidebarItem
+          v-for="route in permission_routes"
+          :key="route.path"
+          :item="route"
+          :base-path="route.path"
+        ></SidebarItem>
+      </el-menu>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+import SidebarItem from "./SidebarItem";
+
+export default {
+  components: { SidebarItem },
+  computed: {
+    ...mapGetters(["permission_routes"]),
+    activeMenu() {
+      const route = this.$route;
+      const { meta, path } = route;
+      // 默认激活项
+      if (meta.activeMenu) {
+        return meta.activeMenu;
+      }
+      return path;
+    },
+    variables() {
+      return {
+        menuText: "#ffffff",  // "#bfcbd9"
+        menuActiveText: "#ffffff",
+        menuBg:  "#001529"
+       
+      };
+    }
+  },
+  mounted() {
+    // console.log(this.permission_routes,12)
+  }
+};
+</script>
+
+<style scoped>
+.sidebar {
+  width: 100%;
+  height: 100%;
+}
+.sidebar-title {
+  width: 100%;
+  height: 50px;
+  border-bottom: 1px solid #dcdfe6;
+  color: #ffffff;
+  box-sizing: border-box;
+  text-align: center;
+  line-height: 50px;
+  font-size: 16px;
+}
+.sidebar-box {
+  width: 100%;
+  height: calc(100% - 64px);
+  overflow-x: hidden;
+  overflow-y: auto;
+  -ms-overflow-style: none;
+  overflow: "-moz-scrollbars-none";
+  scrollbar-width: none; /*  火狐   */
+}
+.sidebar-box::-webkit-scrollbar {
+  display: none; /*  Chrome  */
+  width: 0 !important ; /*  Chrome  */
+}
+.el-menu-vertical-demo:not(.el-menu--collapse) {
+    width: 200px;
+    min-height: 400px;
+  }
+</style>

+ 72 - 0
src/components/TageView/ScrollPane.vue

@@ -0,0 +1,72 @@
+<template>
+  <div class="scroll-container" ref="scrollContainer" @wheel.prevent="handleScroll">
+    <div class="scroll-wrapper" ref="scrollWrapper" :style="{left: left + 'px'}">
+      <slot></slot>
+    </div>
+  </div>
+</template>
+
+<script>
+const padding = 15 // tag's padding
+
+export default {
+  name: 'scrollPane',
+  data() {
+    return {
+      left: 0
+    }
+  },
+  methods: {
+    handleScroll(e) {
+      const eventDelta = e.wheelDelta || -e.deltaY * 3
+      const $container = this.$refs.scrollContainer
+      const $containerWidth = $container.offsetWidth
+      const $wrapper = this.$refs.scrollWrapper
+      const $wrapperWidth = $wrapper.offsetWidth
+
+      if (eventDelta > 0) {
+        this.left = Math.min(0, this.left + eventDelta)
+      } else {
+        if ($containerWidth - padding < $wrapperWidth) {
+          if (this.left < -($wrapperWidth - $containerWidth + padding)) {
+            this.left = this.left
+          } else {
+            this.left = Math.max(this.left + eventDelta, $containerWidth - $wrapperWidth - padding)
+          }
+        } else {
+          this.left = 0
+        }
+      }
+    },
+    moveToTarget($target) {
+      const $container = this.$refs.scrollContainer
+      const $containerWidth = $container.offsetWidth
+      const $targetLeft = $target.offsetLeft
+      const $targetWidth = $target.offsetWidth
+
+      if ($targetLeft < -this.left) {
+        // tag in the left
+        this.left = -$targetLeft + padding
+      } else if ($targetLeft + padding > -this.left && $targetLeft + $targetWidth < -this.left + $containerWidth - padding) {
+        // tag in the current view
+        // eslint-disable-line
+      } else {
+        // tag in the right
+        this.left = -($targetLeft - ($containerWidth - $targetWidth) + padding)
+      }
+    }
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+.scroll-container {
+  white-space: nowrap;
+  position: relative;
+  overflow: hidden;
+  width: 100%;
+  .scroll-wrapper {
+    position: absolute;
+  }
+}
+</style>

+ 204 - 0
src/components/TageView/TagsView.vue

@@ -0,0 +1,204 @@
+<template>
+  <div class="tags-view-container">
+    <scroll-pane class='tags-view-wrapper' ref='scrollPane'>
+      <router-link ref='tag' class="tags-view-item" :class="isActive(tag)?'active':''" v-for="tag in Array.from(visitedViews)"
+        :to="tag.path" :key="tag.path" @contextmenu.prevent.native="openMenu(tag,$event)">
+        {{tag.title}}
+        <span class='el-icon-close' @click.prevent.stop='closeSelectedTag(tag)'></span>
+      </router-link>
+    </scroll-pane>
+    <ul class='contextmenu' v-show="visible" :style="{left:left+'px',top:top+'px'}">
+      <li @click="closeSelectedTag(selectedTag)">关闭</li>
+      <li @click="closeOthersTags">关闭其它</li>
+      <li @click="closeAllTags">关闭所有</li>
+    </ul>
+  </div>
+</template>
+
+<script>
+import ScrollPane from './ScrollPane'
+
+export default {
+  components: { ScrollPane },
+  data() {
+    return {
+      visible: false,
+      top: 0,
+      left: 0,
+      selectedTag: {}
+    }
+  },
+  computed: {
+    visitedViews() {
+      return this.$store.state.tagsView.visitedViews
+    }
+  },
+  watch: {
+    $route() {
+      this.addViewTags()
+      this.moveToCurrentTag()
+    },
+    visible(value) {
+      if (value) {
+        document.body.addEventListener('click', this.closeMenu)
+      } else {
+        document.body.removeEventListener('click', this.closeMenu)
+      }
+    }
+  },
+  mounted() {
+    this.addViewTags()
+  },
+  methods: {
+    generateRoute() {
+      if (this.$route.name) {
+        return this.$route
+      }
+      return false
+    },
+    isActive(route) {
+      return route.path === this.$route.path // || route.name === this.$route.name
+    },
+    addViewTags() {
+      const route = this.generateRoute()
+      if (!route) {
+        return false
+      }
+      this.$store.dispatch('addVisitedViews', route)
+    },
+    moveToCurrentTag() {
+      const tags = this.$refs.tag
+      this.$nextTick(() => {
+        for (const tag of tags) {
+          if (tag.to === this.$route.path) {
+            this.$refs.scrollPane.moveToTarget(tag.$el)
+            break
+          }
+        }
+      })
+    },
+    closeSelectedTag(view) {
+      this.$store.dispatch('delVisitedViews', view).then((views) => {
+        if (this.isActive(view)) {
+          const latestView = views.slice(-1)[0]
+          if (latestView) {
+            this.$router.push(latestView.path)
+          } else {
+            this.$router.push('/')
+          }
+        }
+      })
+    },
+    closeOthersTags() {
+      this.$router.push(this.selectedTag.path)
+      this.$store.dispatch('delOthersViews', this.selectedTag).then(() => {
+        this.moveToCurrentTag()
+      })
+    },
+    closeAllTags() {
+      this.$store.dispatch('delAllViews')
+      this.$router.push('/')
+    },
+    openMenu(tag, e) {
+      this.visible = true
+      this.selectedTag = tag
+      this.left = e.clientX
+      this.top = e.clientY
+    },
+    closeMenu() {
+      this.visible = false
+    }
+  }
+}
+</script>
+
+<style rel="stylesheet/scss" lang="scss" scoped>
+.tags-view-container {
+  .tags-view-wrapper {
+    background: rgba(255, 255, 255, .8);
+    height: 34px;
+    border-bottom: 1px solid #d8dce5;
+    box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
+    .tags-view-item {
+      display: inline-block;
+      position: relative;
+      height: 26px;
+      line-height: 26px;
+      border: 1px solid #d8dce5;
+      color: #495060;
+      background: rgba(255, 255, 255, .8);
+      padding: 0 10px;
+      font-size: 12px;
+      margin-left: 7px;
+      margin-top: 4px;
+      border-radius: 3px;
+      &:first-of-type {
+        margin-left: 15px;
+      }
+      &.active {
+        background-color: #0BADF9;
+        color: #fff;
+        border-color: #0BADF9; //#42b983
+        &::before {
+          content: '';
+          background: #fff;
+          display: inline-block;
+          width: 8px;
+          height: 8px;
+          border-radius: 50%;
+          position: relative;
+          margin-right: 2px;
+        }
+      }
+    }
+  }
+  .contextmenu {
+    margin: 0;
+    background: #fff;
+    z-index: 2;
+    position: absolute;
+    list-style-type: none;
+    padding: 5px 0;
+    border-radius: 4px;
+    font-size: 12px;
+    font-weight: 400;
+    color: #333;
+    box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);
+    li {
+      margin: 0;
+      padding: 7px 16px;
+      cursor: pointer;
+      &:hover {
+        background: #eee;
+      }
+    }
+  }
+}
+</style>
+
+<style rel="stylesheet/scss" lang="scss">
+//reset element css of el-icon-close
+.tags-view-wrapper {
+  .tags-view-item {
+    .el-icon-close {
+      width: 16px;
+      height: 16px;
+      vertical-align: 2px;
+      border-radius: 50%;
+      text-align: center;
+      transition: all .3s cubic-bezier(.645, .045, .355, 1);
+      transform-origin: 100% 50%;
+      margin-left: 3px;
+      &:before {
+        transform: scale(.6);
+        display: inline-block;
+        vertical-align: -3px;
+      }
+      &:hover {
+        background-color: #F9470B; //#b4bccc
+        color: #fff;
+      }
+    }
+  }
+}
+</style>

+ 81 - 0
src/components/analyze/cards.vue

@@ -0,0 +1,81 @@
+<template>
+    <el-col :xs="12" :sm="12" :md="8" :lg="6" :xl="6" style="margin-bottom: 20px;">
+        <div class="index-sales-list" :style="{ borderColor : colors}">
+            <div class="index-sales-list-name">
+                {{name}}
+            </div>
+             <div class="index-sales-list-main"  :style="{ background : colors}">
+                <div class="index-sales-list-main-icon">
+                    <DealSvg v-if="ionc == 'DealSvg'" class="index-sales-list-main-icon-svg" />
+                    <MoneySvg v-else class="index-sales-list-main-icon-svg" />
+                </div>
+                <div class="index-sales-list-main-number">
+                    <count-to :startVal='0' :endVal='number' :duration='3000'></count-to>
+                </div>
+            </div>
+        </div>
+    </el-col>
+</template>
+
+<script>
+import DealSvg from '../../assets/icon/deal.svg'
+import MoneySvg from '../../assets/icon/money.svg'
+import countTo from 'vue-count-to';
+export default {
+    props:['colors','name','number','ionc'],
+    components:{
+        DealSvg,
+        MoneySvg,
+        countTo
+    }
+}
+</script>
+
+<style scoped>
+.index-sales-list{
+    width: 100%;
+    height: auto;
+    /* border: 1px soild #FFA333; */
+    border: 1px solid #FFA333;
+    border-radius: 5px;
+    box-sizing: border-box;
+}
+.index-sales-list-name{
+    width: 100%;
+    height: 40px;
+    text-align: center;
+    line-height: 40px;
+    font-size: 16px;
+    color: #5C5C5C;
+}
+.index-sales-list-main{
+    width: 100%;
+    height: 60px;
+    background: #FFA333;
+    display: flex;
+    justify-content: space-between;
+}
+.index-sales-list-main-icon{
+    width: 70px;
+    height: 100%;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.index-sales-list-main-icon-svg{
+    width: 35px;
+    height: 35px;
+    color: #ffffff;
+    fill: currentColor; 
+}
+.index-sales-list-main-number{
+    width: 60%;
+    /* background: chartreuse; */
+    text-align: right;
+    font-size: 30px;
+    padding-right: 25px;
+    box-sizing: border-box;
+    line-height: 60px;
+    color: #ffffff;
+}
+</style>

+ 81 - 0
src/components/analyze/client.vue

@@ -0,0 +1,81 @@
+<template>
+    <div class="index-client">
+        <div class="index-client-box">
+            <span class="index-client-box-name">购买来源</span>
+            <div class="index-client-box-select">
+                <el-button-group>
+                    <el-button type="primary" size="mini">近七天</el-button>
+                    <el-button size="mini">本月</el-button>
+                    <el-button size="mini">本年</el-button>
+                </el-button-group>
+            </div>
+            <div class="index-client-box-charts">
+                <ve-pie :data="chartData"></ve-pie>
+            </div>    
+        </div>           
+    </div>
+</template>
+
+<script>
+export default {
+    data(){
+        return {
+            chartData:{
+                columns: ['支付方式', '占比'],
+                rows: [
+                    { '支付方式': '小程序', '占比': 25 },
+                    { '支付方式': 'IOS客户端', '占比': 39 },
+                    { '支付方式': '安卓客户端', '占比': 50 },
+                    { '支付方式': 'H5移动端', '占比': 10 },
+                    { '支付方式': 'PC端', '占比': 5 },
+                ]
+            }
+        }
+    }
+}
+</script>
+<style scoped>
+.index-client{
+    width: 100%;
+    height: auto;
+    background: #ffffff;
+    border-radius: 5px;
+    padding: 15px;
+    box-sizing: border-box;
+}
+.index-client-box{
+    width: 100%;
+    /* height: 200px; */
+    border:  1px solid #E6E6E6;
+    position: relative;
+    padding: 20px 15px;
+    box-sizing: border-box;
+}
+.index-client-box-name{
+    position: absolute;
+    width: 100px;
+    height: 30px;
+    background: #ffffff;
+    display: inline-block;
+    text-align: center;
+    line-height: 30px;
+    font-size: 13px;
+    color: #000000;
+    left: 25px;
+    top: -15px;
+}
+.index-client-box-select{
+    width: 100%;
+    height: 40px;
+    /* background: burlywood; */
+    display: flex;
+    justify-content: flex-end;
+    align-items: center;
+    margin-bottom: 10px;
+}
+.index-client-box-charts{
+    width: 100%;
+    height: 350px;
+    /* background: chocolate; */
+}
+</style>

+ 180 - 0
src/components/analyze/map.vue

@@ -0,0 +1,180 @@
+<template>
+    <div class="index-pay">
+        <div class="index-pay-box">
+            <span class="index-pay-box-name">订单分布</span>
+            <div class="index-pay-box-select">
+                <el-button-group>
+                    <el-button type="primary" size="mini">近七天</el-button>
+                    <el-button size="mini">本月</el-button>
+                    <el-button size="mini">本年</el-button>
+                </el-button-group>
+            </div>
+            <div id="index-pay-box-charts">
+                <div id="myChartChina" :style="{width: '100%', height: '500px'}"></div>
+            </div>    
+        </div>           
+    </div>
+</template>
+
+<script>
+export default {
+    data(){
+        return {
+            
+        }
+    },
+    mounted() {
+        this.drawLine();
+    },
+    methods:{
+        drawLine(){
+        // 基于准备好的dom,初始化echarts实例
+        var myChartContainer = document.getElementById('myChartChina');       
+        var resizeMyChartContainer = function(){
+          myChartContainer.style.width=(document.body.offsetWidth/2)+'px'//页面一半的大小
+        } 
+         resizeMyChartContainer();
+        var myChartChina = this.$echarts.init(myChartContainer); 
+
+        function randomData() {  
+                return Math.round(Math.random()*500);  
+            } 
+        // 绘制图表
+       var optionMap = {  
+              tooltip: {},
+                 legend: {
+                            orient: 'vertical',
+                            left: 'left',
+                            data:['']
+                        },      
+                 visualMap: {
+                            min: 0,
+                            max: 1000,
+                            left: '10%',
+                            top: 'bottom',
+                            text: ['高','低'],
+                            calculable : true,
+                            color:['#158BFE','#ffffff']
+                        },   
+                 selectedMode: 'single',
+                 series : [                         
+                            {
+                              name: '', 
+                              type: 'map',
+                              mapType: 'china',
+                              itemStyle: {
+                                    normal:{
+                                        borderColor: 'rgba(0, 0, 0, 0.2)'
+                                    },
+                                    emphasis:{
+                                        shadowOffsetX: 0,
+                                        shadowOffsetY: 0,
+                                        shadowBlur: 20,
+                                        borderWidth: 0,
+                                        shadowColor: 'rgba(0, 0, 0, 0.5)'
+                                    }
+                                },
+                                showLegendSymbol: true,
+                                label: {
+                                    normal: {
+                                        show: true
+                                    },
+                                    emphasis: {
+                                        show: true
+                                    }
+                                },
+                                data:[               
+                                     {name: '北京',value: randomData() },
+                                      {name: '天津',value: randomData() },
+                                      {name: '上海',value: randomData() },
+                                      {name: '重庆',value: randomData() },
+                                      {name: '河北',value: randomData() },
+                                      {name: '河南',value: randomData() },
+                                      {name: '云南',value: randomData() },
+                                      {name: '辽宁',value: randomData() },
+                                      {name: '黑龙江',value: randomData() },
+                                      {name: '湖南',value: randomData() },
+                                      {name: '安徽',value: randomData() },
+                                      {name: '山东',value: randomData() },
+                                      {name: '新疆',value: randomData() },
+                                      {name: '江苏',value: randomData() },
+                                      {name: '浙江',value: randomData() },
+                                      {name: '江西',value: randomData() },
+                                      {name: '湖北',value: randomData() },
+                                      {name: '广西',value: randomData() },
+                                      {name: '甘肃',value: randomData() },
+                                      {name: '山西',value: randomData() },
+                                      {name: '内蒙古',value: randomData() },
+                                      {name: '陕西',value: randomData() },
+                                      {name: '吉林',value: randomData() },
+                                      {name: '福建',value: randomData() },
+                                      {name: '贵州',value: randomData() },
+                                      {name: '广东',value: randomData() },
+                                      {name: '青海',value: randomData() },
+                                      {name: '西藏',value: randomData() },
+                                      {name: '四川',value: randomData() },
+                                      {name: '宁夏',value: randomData() },
+                                      {name: '海南',value: randomData() },
+                                      {name: '台湾',value: randomData() },
+                                      {name: '香港',value: randomData() },
+                                      {name: '澳门',value: randomData() }
+                                ]
+                            }
+                        ]
+               }
+     
+        myChartChina.setOption(optionMap);
+        window.onresize=function(){
+            resizeMyChartContainer();
+            myChartChina.resize();
+        }
+      }
+    }
+}
+</script>
+
+<style scoped>
+.index-pay{
+    width: 100%;
+    height: auto;
+    background: #ffffff;
+    border-radius: 5px;
+    padding: 15px;
+    box-sizing: border-box;
+}
+.index-pay-box{
+    width: 100%;
+    /* height: 200px; */
+    border:  1px solid #E6E6E6;
+    position: relative;
+    padding: 20px 15px;
+    box-sizing: border-box;
+}
+.index-pay-box-name{
+    position: absolute;
+    width: 100px;
+    height: 30px;
+    background: #ffffff;
+    display: inline-block;
+    text-align: center;
+    line-height: 30px;
+    font-size: 13px;
+    color: #000000;
+    left: 25px;
+    top: -15px;
+}
+.index-pay-box-select{
+    width: 100%;
+    height: 40px;
+    /* background: burlywood; */
+    display: flex;
+    justify-content: flex-end;
+    align-items: center;
+    margin-bottom: 10px;
+}
+#index-pay-box-charts{
+    width: 100%;
+    height: 500px;
+    /* background: chocolate; */
+}
+</style>

+ 125 - 0
src/components/analyze/maps.vue

@@ -0,0 +1,125 @@
+<template>
+    <div class="map">
+        <div id="myChartChina" :style="{width: '100%', height: '500px'}"></div>
+    </div>
+</template>
+
+<script>
+export default {
+    mounted() {
+        this.drawLine();
+    },
+    methods:{
+        drawLine(){
+        // 基于准备好的dom,初始化echarts实例
+        var myChartContainer = document.getElementById('myChartChina');       
+        var resizeMyChartContainer = function(){
+          myChartContainer.style.width=(document.body.offsetWidth/2)+'px'//页面一半的大小
+        } 
+         resizeMyChartContainer();
+        var myChartChina = this.$echarts.init(myChartContainer); 
+
+        function randomData() {  
+                return Math.round(Math.random()*500);  
+            } 
+        // 绘制图表
+       var optionMap = {  
+              tooltip: {},
+                 legend: {
+                            orient: 'vertical',
+                            left: 'left',
+                            data:['']
+                        },      
+                 visualMap: {
+                            min: 0,
+                            max: 1500,
+                            left: '10%',
+                            top: 'bottom',
+                            text: ['高','低'],
+                            calculable : true,
+                            color:['#158BFE','#ffffff']
+                        },   
+                 selectedMode: 'single',
+                 series : [                         
+                            {
+                              name: '', 
+                              type: 'map',
+                              mapType: 'china',
+                              itemStyle: {
+                                    normal:{
+                                        borderColor: 'rgba(0, 0, 0, 0.2)'
+                                    },
+                                    emphasis:{
+                                        shadowOffsetX: 0,
+                                        shadowOffsetY: 0,
+                                        shadowBlur: 20,
+                                        borderWidth: 0,
+                                        shadowColor: 'rgba(0, 0, 0, 0.5)'
+                                    }
+                                },
+                                showLegendSymbol: true,
+                                label: {
+                                    normal: {
+                                        show: true
+                                    },
+                                    emphasis: {
+                                        show: true
+                                    }
+                                },
+                                data:[               
+                                     {name: '北京',value: randomData() },
+                                      {name: '天津',value: randomData() },
+                                      {name: '上海',value: randomData() },
+                                      {name: '重庆',value: randomData() },
+                                      {name: '河北',value: randomData() },
+                                      {name: '河南',value: randomData() },
+                                      {name: '云南',value: randomData() },
+                                      {name: '辽宁',value: randomData() },
+                                      {name: '黑龙江',value: randomData() },
+                                      {name: '湖南',value: randomData() },
+                                      {name: '安徽',value: randomData() },
+                                      {name: '山东',value: randomData() },
+                                      {name: '新疆',value: randomData() },
+                                      {name: '江苏',value: randomData() },
+                                      {name: '浙江',value: randomData() },
+                                      {name: '江西',value: randomData() },
+                                      {name: '湖北',value: randomData() },
+                                      {name: '广西',value: randomData() },
+                                      {name: '甘肃',value: randomData() },
+                                      {name: '山西',value: randomData() },
+                                      {name: '内蒙古',value: randomData() },
+                                      {name: '陕西',value: randomData() },
+                                      {name: '吉林',value: randomData() },
+                                      {name: '福建',value: randomData() },
+                                      {name: '贵州',value: randomData() },
+                                      {name: '广东',value: randomData() },
+                                      {name: '青海',value: randomData() },
+                                      {name: '西藏',value: randomData() },
+                                      {name: '四川',value: randomData() },
+                                      {name: '宁夏',value: randomData() },
+                                      {name: '海南',value: randomData() },
+                                      {name: '台湾',value: randomData() },
+                                      {name: '香港',value: randomData() },
+                                      {name: '澳门',value: randomData() }
+                                ]
+                            }
+                        ]
+               }
+     
+        myChartChina.setOption(optionMap);
+        window.onresize=function(){
+            resizeMyChartContainer();
+            myChartChina.resize();
+        }
+      }
+    }
+}
+</script>
+
+<style scoped>
+.map{
+    width: 100%;
+    height: 500px;
+    background: #ffffff;
+}
+</style>

+ 98 - 0
src/components/analyze/monitorcar.vue

@@ -0,0 +1,98 @@
+<template>
+    
+    <div class="monitor-cart-list" :style="{borderColor: color}">
+        <div class="monitor-cart-list-name">
+            {{name}}
+        </div>
+        <div class="monitor-cart-list-number" :style="{background: color}">
+            <div class="monitor-cart-list-number-left">
+                <ViewsSvg v-if="icon == 'ViewsSvg' " class="monitor-cart-list-number-left-icon" />
+                <SalesSvg v-if="icon == 'SalesSvg' " class="monitor-cart-list-number-left-icon" />
+                <OrderSvg v-if="icon == 'OrderSvg' " class="monitor-cart-list-number-left-icon" />
+                <RegistrationSvg v-if="icon == 'RegistrationSvg' " class="monitor-cart-list-number-left-icon" />
+            </div>
+            <div class="monitor-cart-list-number-right">
+               <count-to :startVal='0' :endVal='number' :duration='3000'></count-to>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import ViewsSvg from '../../assets/icon/views.svg'
+import SalesSvg from '../../assets/icon/sales.svg'
+import OrderSvg from '../../assets/icon/order.svg'
+import RegistrationSvg from '../../assets/icon/registration.svg'
+
+import countTo from 'vue-count-to';
+export default {
+    props:['name','number','color','icon'],
+    components:{
+        ViewsSvg,
+        SalesSvg,
+        OrderSvg,
+        RegistrationSvg,
+        countTo
+    }
+}
+</script>
+
+<style scoped>
+.monitor-cart-list{
+    width: 100%;
+    height: auto;
+    background: #ffffff;
+    border-radius: 10px;
+    border: 1px solid #F141AF;
+    box-sizing: border-box;
+    overflow: hidden;
+    margin-bottom: 20px;
+}
+.monitor-cart-list-name{
+    width: 100%;
+    height: 42px;
+    /* border-bottom: 1px solid #E8EAEC; */
+    padding: 0 15px;
+    box-sizing: border-box;
+    line-height: 42px;
+    color: #5C5C5C;
+
+}
+.monitor-cart-list-number{
+    width: 100%;
+    height: 68px;
+    padding-left: 15px;
+    padding-right: 15px;
+    box-sizing: border-box;
+    color: #515a6e;
+    font-size: 30px;
+    line-height: 68px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    background: #F141AF;
+}
+.monitor-cart-list-number-left{
+    width: 80px;
+    height: 50px;
+    /* background: burlywood; */
+    border-radius: 5px;
+    text-align: center;
+    line-height: 50px;
+}
+.monitor-cart-list-number-left-icon{
+    width: 30px;
+    height: 30px;
+    fill: currentColor;
+    color: #ffffff;
+    font-weight: bold;
+}
+.monitor-cart-list-number-right{
+    width: 60%;
+    height: 50px;
+    line-height: 50px;
+    font-size: 30px;
+    text-align: right;
+    color: #ffffff;
+}
+</style>

+ 79 - 0
src/components/analyze/pay.vue

@@ -0,0 +1,79 @@
+<template>
+    <div class="index-pay">
+        <div class="index-pay-box">
+            <span class="index-pay-box-name">支付方式</span>
+            <div class="index-pay-box-select">
+                <el-button-group>
+                    <el-button type="primary" size="mini">近七天</el-button>
+                    <el-button size="mini">本月</el-button>
+                    <el-button size="mini">本年</el-button>
+                </el-button-group>
+            </div>
+            <div class="index-pay-box-charts">
+                <ve-pie :data="chartData"></ve-pie>
+            </div>    
+        </div>           
+    </div>
+</template>
+
+<script>
+export default {
+    data(){
+        return {
+            chartData:{
+                columns: ['支付方式', '占比'],
+                rows: [
+                    { '支付方式': '支付宝', '占比': 35 },
+                    { '支付方式': '微信', '占比': 39 },
+                    { '支付方式': '余额', '占比': 26 },
+                ]
+            }
+        }
+    }
+}
+</script>
+<style scoped>
+.index-pay{
+    width: 100%;
+    height: auto;
+    background: #ffffff;
+    border-radius: 5px;
+    padding: 15px;
+    box-sizing: border-box;
+}
+.index-pay-box{
+    width: 100%;
+    /* height: 200px; */
+    border:  1px solid #E6E6E6;
+    position: relative;
+    padding: 20px 15px;
+    box-sizing: border-box;
+}
+.index-pay-box-name{
+    position: absolute;
+    width: 100px;
+    height: 30px;
+    background: #ffffff;
+    display: inline-block;
+    text-align: center;
+    line-height: 30px;
+    font-size: 13px;
+    color: #000000;
+    left: 25px;
+    top: -15px;
+}
+.index-pay-box-select{
+    width: 100%;
+    height: 40px;
+    /* background: burlywood; */
+    display: flex;
+    justify-content: flex-end;
+    align-items: center;
+    margin-bottom: 10px;
+}
+.index-pay-box-charts{
+    width: 100%;
+    height: 350px;
+    /* background: chocolate; */
+}
+</style>

+ 114 - 0
src/components/analyze/product.vue

@@ -0,0 +1,114 @@
+<template>
+    <div class="index-product">
+        <div class="index-product-box">
+            <span class="index-product-box-name">热销产品Top 10</span>
+            <div class="index-product-box-select">
+                <el-button-group>
+                    <el-button type="primary" size="mini">近七天</el-button>
+                    <el-button size="mini">本月</el-button>
+                    <el-button size="mini">本年</el-button>
+                </el-button-group>
+            </div>
+            <div class="index-product-box-charts">
+                <dv-scroll-ranking-board :config="config" style="width:500px;height:450px; color: red;" />
+            </div>    
+        </div>           
+    </div>
+</template>
+
+<script>
+export default {
+    data(){
+        return {
+            config:{
+                data:   [
+                        {
+                        name: '周口',
+                        value: 55
+                        },
+                        {
+                        name: '南阳',
+                        value: 120
+                        },
+                        {
+                        name: '西峡',
+                        value: 78
+                        },
+                        {
+                        name: '驻马店',
+                        value: 66
+                        },
+                        {
+                        name: '新乡',
+                        value: 80
+                        },
+                        {
+                        name: '新乡',
+                        value: 26
+                        },
+                        {
+                        name: '新乡',
+                        value: 20
+                        },
+                        {
+                        name: '新乡',
+                        value: 13
+                        },
+                        {
+                        name: '新乡',
+                        value: 10
+                        }
+                    ],
+                unit: '件',
+                rowNum: 10
+            }
+            
+        }
+    }
+}
+</script>
+<style scoped>
+.index-product{
+    width: 100%;
+    height: auto;
+    background: #ffffff;
+    border-radius: 5px;
+    padding: 15px;
+    box-sizing: border-box;
+}
+.index-product-box{
+    width: 100%;
+    /* height: 200px; */
+    border:  1px solid #E6E6E6;
+    position: relative;
+    padding: 20px 15px;
+    box-sizing: border-box;
+}
+.index-product-box-name{
+    position: absolute;
+    width: 100px;
+    height: 30px;
+    background: #ffffff;
+    display: inline-block;
+    text-align: center;
+    line-height: 30px;
+    font-size: 13px;
+    color: #000000;
+    left: 25px;
+    top: -15px;
+}
+.index-product-box-select{
+    width: 100%;
+    height: 40px;
+    /* background: burlywood; */
+    display: flex;
+    justify-content: flex-end;
+    align-items: center;
+    margin-bottom: 10px;
+}
+.index-product-box-charts{
+    width: 100%;
+    height: 500px;
+    /* background: chocolate; */
+}
+</style>

+ 45 - 0
src/directive/permission.js

@@ -0,0 +1,45 @@
+// 封装一个指令v-permission,从而实现按钮级别权限控制
+import store from '@/store'
+/**
+ * 指令的使用
+ * v-permission="['admin','editor']"
+ * 
+*/
+const permission = {
+    inserted(el, binding){ 
+        /**
+         * el 当前指令的元素  
+         * binding {name,expression,vale}等
+         * */ 
+        // 获取指令的值: 按钮要求的角色数组
+        const { value: pRoles } = binding;
+        //  获取用户角色
+        const roles = store.getters && store.getters.roles
+
+        if(pRoles && pRoles instanceof Array && pRoles.length >0 ){
+            // 判断用户角色中是否有按钮要求的角色
+            const hasPermission = roles.some(role => {
+                return pRoles.includes(role);
+            })
+            // console.log(hasPermission)
+            // 如果没有权限则删除当前DOM
+            if(!hasPermission){
+                el.parentNode && el.parentNode.removeChild(el);
+            }
+        }else{
+            throw new Error(`需要指定按钮要求角色数组,如v-permission="['admin','editor']"`)
+        }
+    }
+}
+
+export default permission;
+
+
+/**
+ * 全局注册指令
+ * import vPermission from './directive/permission'
+ * Vue.directive('permission',vPermission)
+ * 
+ * 使用 <button v-permission="['admin']">admin</button>
+ * 
+ * */ 

+ 75 - 0
src/http/index.js

@@ -0,0 +1,75 @@
+import axios from 'axios'
+import { MessageBox, Message } from 'element-ui'
+import store from '../store/index'
+import { getToken } from '@/utils/auth';
+
+// 创建axios实例
+const service = axios.create({
+    baseURL: process.env.VUE_APP_BASE_API, //URL地址   环境变量文件 .env.development
+    timeout: 5000 ,//超时
+    withCredentials: true,  //跨域时若要发生cookie,需要设置该选项
+})
+
+// 请求拦截器
+service.interceptors.request.use(
+    config => {
+        if(store.getters.token){
+            // 设置令牌请求头
+            config.headers['Authorization'] = getToken()
+        }
+    },
+    error => {
+        return Promise.reject(error)
+    }
+)
+
+// 相应拦截
+service.interceptors.response.use(
+    // 通过自定义code 判定响应状态 也可以通过HTTP状态码判断
+    response =>{
+        const res = response.data
+
+        // code 不为0 则判断为一个错误
+        if(res.code !== 0){
+            Message({
+                message: res.msg || "Error",
+                type: 'error',
+                duration: 5*1000
+            })
+        
+
+            // 假设 10008 非法令牌  10012 其他客户端已经登陆
+            if(res.code === 10008 || res.code === 10012){
+                // 重新登陆
+                MessageBox.confirm(
+                    '登陆状态异常,请重新登陆',
+                    "确认登陆信息",
+                    {
+                        confirmButtonText: '重新登陆',
+                        cancelButtonText: '取消',
+                        type: 'warning'
+                    }
+                ).then(()=>{
+                    store.dispatch('user/resetToken')
+                        .then(()=>{
+                            location.reload()
+                        })
+                })
+            }
+
+            return Promise.reject(new Error(res.message || 'Error'));
+    
+        }else{
+            return res;
+        }
+    },
+    error =>{
+        Message({
+            message: error.message,
+            type: 'error',
+            duration: 5*1000
+        })
+    }
+)
+
+export default service;

+ 224 - 0
src/layout/index.vue

@@ -0,0 +1,224 @@
+<template>
+    <div class="app-wrapper">
+        <el-container class="app-box">
+            <el-aside :width="asideShow ? '200px' : '0px'" class="main-aside" :style="themeColor[themeIndex].aside">
+                    <sidebar class="sidebar-container"></sidebar>
+            </el-aside>
+            <el-container class="main">
+                <el-header class="heads" height='50px' :style="themeColor[themeIndex].header">
+                    <Headers :asideShow.sync="asideShow" @targetIcon='targetIcon' :themeColor='themeColor' :themeIndex='themeIndex' @targetThemeIndex='targetThemeIndex'></Headers>
+                </el-header>
+                <el-main class="main-container">
+                    <TagsViews />
+                    <div class="main-container-views" :style="themeColor[themeIndex].container">
+                        <transition name="nodebook" mode="out-in">
+                            <router-view />
+                        </transition>
+                        
+                    </div>
+                </el-main>
+            </el-container>
+        </el-container>
+        <el-backtop target=".main-container-views" :bottom="100">
+            <div class="scrollTop" >
+            <i class="el-icon-upload2" ></i>
+            </div>
+        </el-backtop>
+        
+    </div>
+</template>
+
+<script>
+import Sidebar from '../components/Sidebar/index.vue'
+import Headers from '../components/Headers/Headers.vue'
+import TagsViews from '../components/TageView/TagsView.vue'
+
+// 获取本地存储的主题
+import { getTheme, setTheme } from '@/utils/theme'
+let Theme = parseInt(getTheme()) || 0
+
+let themeColor =[
+    {
+        aside: 'background-image: linear-gradient(#001529, #001529);',
+        header: 'background-image: linear-gradient(to right,#ffffff, #ffffff);',
+        container: 'background-image: linear-gradient(to bottom right,#ffffff,#ffffff);'
+    },
+    {
+        aside: 'background-image: linear-gradient(#00BCFF, #00BCFF);',
+        header: 'background-image: linear-gradient(to right,#D2F2F1, #D2F2F1);',
+        container: 'background-image: linear-gradient(to bottom right,#D2F2F1,#D2F2F1);'
+    },
+    {
+        aside: 'background-image: linear-gradient(#9E25B0, #9E25B0);',
+        header: 'background-image: linear-gradient(to right,#EBD4F1, #EBD4F1);',
+        container: 'background-image: linear-gradient(to bottom right,#EBD4F1,#EBD4F1);'
+    },
+    {
+        aside: 'background-image: linear-gradient(#E13998, #E13998);',
+        header: 'background-image: linear-gradient(to right,#F9D6E9, #F9D6E9);',
+        container: 'background-image: linear-gradient(to bottom right,#F9D6E9,#F9D6E9);'
+    },
+    {
+        aside: 'background-image: linear-gradient(#E54E43, #E54E43);',
+        header: 'background-image: linear-gradient(to right,#FBD3D0, #FBD3D0);',
+        container: 'background-image: linear-gradient(to bottom right,#FBD3D0,#FBD3D0);'
+    },
+    {
+        aside: 'background-image: linear-gradient(#E13998, #F0F0F0);',
+        header: 'background-image: linear-gradient(to right,#EDC6DC, #ffffff);',
+        container: 'background-image: linear-gradient(to bottom right,#E13998,#F0F0F0);'
+    },
+    {
+        aside: 'background-image: linear-gradient(#F2791C, #F0F0F0);',
+        header: 'background-image: linear-gradient(to right,#F0D9C8, #ffffff);',
+        container: 'background-image: linear-gradient(to bottom right,#F2791C,#F0F0F0);'
+    },
+    
+    {
+        aside: 'background-image: linear-gradient(#FABC07, #F0F0F0);',
+        header: 'background-image: linear-gradient(to right,#F2E8CA, #ffffff);',
+        container: 'background-image: linear-gradient(to bottom right,#FABC07,#F0F0F0);'
+    },
+    
+    {
+        aside: 'background-image: linear-gradient(#9F23B2, #F0F0F0);',
+        header: 'background-image: linear-gradient(to right,#E1C9E4, #ffffff);',
+        container: 'background-image: linear-gradient(to bottom right,#9F23B2,#F0F0F0);'
+    },
+    {
+        aside: 'background-image: linear-gradient(#1BBCB4, #8CC63E);',
+        header: 'background-image: linear-gradient(to right,#ffffff,#1BBCB4, #ffffff);',
+        container: 'background-image: linear-gradient(to bottom right,#1BBCB4,#8CC63E);'
+    },
+    {
+        aside: 'background-image: linear-gradient(#E44D42, #FBBD08);',
+        header: 'background-image: linear-gradient(to right,#ffffff,#F37A1D, #ffffff);',
+        container: 'background-image: linear-gradient(to bottom right,#F37A1D, #FBBD08);'
+    },
+    {
+        aside: 'background-image: linear-gradient(#1AB8B8, #6F36B4);',
+        header: 'background-image: linear-gradient(to right,#ffffff,#1AB8B8, #ffffff);',
+        container: 'background-image: linear-gradient(to bottom right,#1AB8B8, #6F36B4);'
+    },
+    {
+        aside: 'background-image: linear-gradient(#EE2521, #FC8B02);',
+        header: 'background-image: linear-gradient(to right,#ffffff,#EE2521, #ffffff);',
+        container: 'background-image: linear-gradient(to bottom right,#EE2521, #FC8B02);'
+    },
+    {
+        aside: 'background-image: linear-gradient(#6D35B3, #E6058F);',
+        header: 'background-image: linear-gradient(to right,#ffffff,#6D35B3, #ffffff);',
+        container: 'background-image: linear-gradient(to bottom right,#6D35B3, #E6058F);'
+    },
+    {
+        aside: 'background-image: linear-gradient(#F83FBD, #CE1DFC);',
+        header: 'background-image: linear-gradient(to right,#ffffff,#F83FBE, #ffffff);',
+        container: 'background-image: linear-gradient(to bottom right,#F83FBD, #CE1DFC);'
+    }
+]
+export default {
+    data(){
+        return {
+            asideShow: true,
+            themeIndex: Theme,   //当前配色方案
+            themeColor:themeColor  //配色方案
+        }
+    },
+    components: {
+        Sidebar,
+        Headers,
+        TagsViews
+    },
+    methods:{
+        targetIcon(boole){
+            this.asideShow = boole
+        },
+        // 配色方案 子元素自定义事件
+        targetThemeIndex(index){
+            this.themeIndex = index
+            setTheme(index)
+        }
+    }
+}
+</script>
+
+<style>
+.app-wrapper{
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+}
+.app-box{
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    transition: all 2s;
+}
+.heads{
+    margin: 0;
+    padding: 0;
+    border-bottom: 1px solid #dcdfe6;
+    /* background-image: linear-gradient(#1AB8B8, #f7f7f7); */
+}
+.main{
+    width: 100%;
+    height: 100%;
+    overflow: hidden!important;
+}
+.main-aside{
+    height: 100%;
+    /* background: #001529; */
+    /* background-image: linear-gradient(#3DBCFD, #97DBFE,#30D791); */
+    background-image: linear-gradient(#1AB8B8, #6F36B4);
+     /* background-image: linear-gradient(#1AB8B8,#FF9500,#E5038F, #7234B2, #ED1E23); */
+    transition:  all 0.5s;
+}
+.main-container{
+    width: 100%;
+    height: 100%;
+    padding: 0 !important;
+}
+.el-menu{
+    border: none !important;
+}
+.main-container-views{
+    width: 100%;
+    height: calc(100% - 35px);
+    overflow-x: hidden;
+    overflow-y: auto;
+    -ms-overflow-style: none; 
+    overflow: '-moz-scrollbars-none';
+    scrollbar-width: none;  /*  火狐   */
+    background: #F5F7F9;
+    background-image: linear-gradient(#1AB8B8, #3BB54A);
+}
+.main-container-views::-webkit-scrollbar {
+    display: none;  /*  Chrome  */
+    width: 0 !important ; /*  Chrome  */
+  }
+
+.scrollTop{
+    height: 100%;
+    width: 100%;
+    background-color: #f2f5f6;
+    box-shadow: 0 0 6px rgba(0,0,0, .5);
+    text-align: center;
+    line-height: 40px;
+    color: #1989fa;
+    font-size: 30px;
+    font-weight: bolder;
+}
+
+.nodebook-enter, .nodebook-leave-to{
+    transform: scale(0.9);
+    opacity: 0;
+}
+
+.nodebook-enter-to, .nodebook-leave{
+    transform: scale(1);
+    opacity: 1;
+}
+.nodebook-enter-active, .nodebook-leave-active {
+    transition: all 0.3s;
+}
+</style>

+ 64 - 0
src/main.js

@@ -0,0 +1,64 @@
+import Vue from 'vue'
+import App from './App.vue'
+import router from './router'
+import store from './store'
+
+import ElementUI from 'element-ui';
+import 'element-ui/lib/theme-chalk/index.css';
+
+// 引入进度条样式
+import 'nprogress/nprogress.css'
+
+//引入自定义滚动条
+import HappyScroll from 'vue-happy-scroll'
+import 'vue-happy-scroll/docs/happy-scroll.css'
+
+//自动滚动插件
+import scroll from 'vue-seamless-scroll'
+
+// 引入cookie
+import cookie from 'js-cookie'
+Vue.prototype.$cookie = cookie;
+
+// 炫酷的粒子动效
+import  VueParticles  from   'vue-particles'
+
+// 引入图表
+import VCharts from 'v-charts'
+
+Vue.use(VCharts)
+
+// 制作地图
+import echarts from 'echarts'
+Vue.prototype.$echarts = echarts
+import china from 'echarts/map/json/china.json'
+echarts.registerMap('china', china)
+
+// 炫酷图标
+import dataV from '@jiaminghi/data-view'
+
+Vue.use(dataV)
+
+
+Vue.config.productionTip = false
+
+Vue.use(HappyScroll)
+
+Vue.use(scroll)
+
+Vue.use(VueParticles)
+
+Vue.use(ElementUI);
+
+// 全局路由守卫
+import './router/permission'
+
+// 全局注册指令
+import vPermission from './directive/permission'
+Vue.directive('permission',vPermission)
+
+new Vue({
+  router,
+  store,
+  render: h => h(App)
+}).$mount('#app')

+ 384 - 0
src/router/index.js

@@ -0,0 +1,384 @@
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+
+import Layout from '@/layout' //布局页
+
+
+
+Vue.use(VueRouter)
+
+// 通用页面, 这里的配置不需要权限
+export const constRouter = [
+  {
+      path: '/login',
+      component: () => import('@/views/login/Login'),
+      hidden: true //导航菜单忽略选项
+  },
+  {
+      path: '',
+      component: Layout, //应用布局页
+      redirect: '/index',
+      hidden: true,
+  },
+  {
+      path: '/index',
+      component: Layout, //应用布局页
+      name: 'index',
+      meta:{
+          title: "首页", //导航菜单项标题
+          icon: 'el-icon-s-home' //导航菜单图标
+      },
+      children: [
+        {
+          path: '',
+          component: () => import('@/views/index/index.vue'),
+          name: 'indexs',
+          meta: {
+            title: "工作台",
+            icon: 'el-icon-s-home',
+            roles: ['admin','jerry']
+          }
+        }
+      ]
+  }
+]
+
+// 动态路由 communication
+export const asyncRoutes = [
+  {
+    path: '/analyze',
+    component: Layout,
+    redirect: '/goods/index',
+    meta: {
+      title: "数据分析",
+      icon: 'el-icon-s-marketing',
+      hidden: false
+    },
+    children: [
+      {
+        path: 'analyzeindex',
+        component: () => import('@/views/analyze/Index.vue'),
+        name: 'analyzeindex',
+        meta: {
+          title: "主控数据",
+          icon: 'el-icon-tickets',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'analyzemonitor',
+        component: () => import('@/views/analyze/Monitor.vue'),
+        name: 'analyzemonitor',
+        meta: {
+          title: "监控数据",
+          icon: 'el-icon-tickets',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+    ]
+  },
+  {
+    path: '/goods',
+    component: Layout,
+    redirect: '/goods/index',
+    meta:{
+      title: "玩家数据",
+      icon: 'el-icon-s-goods',
+      hidden: false,
+    },
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/goods/Index.vue'),
+        name: 'goodsindex',
+        meta: {
+          title: "玩家信息",
+          icon: 'el-icon-tickets',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'fromgood',
+        component: () => import('@/views/goods/FromGood.vue'),
+        name: 'fromgood',
+        meta: {
+          title: "添加(编辑产品)",
+          icon: 'el-icon-tickets',
+          hidden: true,
+          roles: ['admin','jerry'],
+          
+        }
+      },
+      {
+        path: 'onindex',
+        component: () => import('@/views/goods/OnIndex.vue'),
+        name: 'onindex',
+        meta: {
+          title: "待上架产品",
+          icon: 'el-icon-tickets',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'offindex',
+        component: () => import('@/views/goods/OffIndex.vue'),
+        name: 'offindex',
+        meta: {
+          title: "已下架产品",
+          icon: 'el-icon-tickets',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'sort',
+        component: () => import('@/views/goods/Sort.vue'),
+        name: 'sort',
+        meta: {
+          title: "产品分类",
+          icon: 'el-icon-tickets',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+    ]
+  },
+  {
+    path: '/control',
+    component: Layout,
+    redirect: '/control/keycode',
+    meta:{
+      title: "布局控制",
+      icon: 'el-icon-s-platform',
+      hidden: false,
+    },
+    children: [
+      {
+        path: 'keycode',
+        component: () => import('@/views/control/KeyCode.vue'),
+        name: 'keycode',
+        meta: {
+          title: "关键词",
+          icon: 'el-icon-message',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'placard',
+        component: () => import('@/views/control/Placard.vue'),
+        name: 'placard',
+        meta: {
+          title: "公告",
+          icon: 'el-icon-message',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'carousel',
+        component: () => import('@/views/control/Carousel.vue'),
+        name: 'carousel',
+        meta: {
+          title: "首页轮播图",
+          icon: 'el-icon-message',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'ad',
+        component: () => import('@/views/control/Ad.vue'),
+        name: 'ad',
+        meta: {
+          title: "广告图",
+          icon: 'el-icon-message',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'nav',
+        component: () => import('@/views/control/Nav.vue'),
+        name: 'nav',
+        meta: {
+          title: "首页导航",
+          icon: 'el-icon-message',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+    ]
+  },
+  {
+    path: '/marketing',
+    component: Layout,
+    redirect: '/marketing/spike',
+    meta:{
+      title: "营销控制",
+      icon: 'el-icon-s-help',
+      hidden: false,
+    },
+    children: [
+      {
+        path: 'spike',
+        component: () => import('@/views/marketing/Spike.vue'),
+        name: 'spike',
+        meta: {
+          title: "秒杀时间段",
+          icon: 'el-icon-message',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'produce',
+        component: () => import('@/views/marketing/Produce.vue'),
+        name: 'produce',
+        meta: {
+          title: "秒杀产品",
+          icon: 'el-icon-message',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'area',
+        component: () => import('@/views/marketing/Area.vue'),
+        name: 'area',
+        meta: {
+          title: "特色专区",
+          icon: 'el-icon-message',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'choice',
+        component: () => import('@/views/marketing/Choice.vue'),
+        name: 'choice',
+        meta: {
+          title: "精选分类",
+          icon: 'el-icon-message',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+    ]
+  },
+  {
+    path: '/coupon',
+    component: Layout,
+    redirect: '/coupon/addCoupon',
+    meta:{
+      title: "卡券管理",
+      icon: 'el-icon-s-help',
+      hidden: false,
+    },
+    children: [
+      {
+        path: 'addCoupon',
+        component: () => import('@/views/coupon/AddCoupon.vue'),
+        name: 'addCoupon',
+        meta: {
+          title: "优惠券类型",
+          icon: 'el-icon-message',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'couponlist',
+        component: () => import('@/views/coupon/CouponList.vue'),
+        name: 'couponlist',
+        meta: {
+          title: "优惠券列表",
+          icon: 'el-icon-message',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+    ]
+  },
+  {
+    path: '/communication',
+    component: Layout,
+    redirect: '/communication/index',
+    meta:{
+      title: "通讯",
+      icon: 'el-icon-s-help',
+      hidden: false,
+    },
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/communication/Index.vue'),
+        name: 'communicationindex',
+        meta: {
+          title: "邮件",
+          icon: 'el-icon-message',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'wechat',
+        component: () => import('@/views/communication/WeChat.vue'),
+        name: 'communicationwechat',
+        meta: {
+          title: "客服",
+          icon: 'el-icon-service',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+    ]
+  },
+  {
+    path: '/home',
+    component: Layout,
+    redirect: '/home/index',
+    meta:{
+      title: "个人中心",
+      icon: 'el-icon-user-solid',
+      hidden: false,
+    },
+    children: [
+      {
+        path: 'index',
+        component: () => import('@/views/home/Index.vue'),
+        name: 'homeindex',
+        meta: {
+          title: "个人设置",
+          icon: 'el-icon-user-solid',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+      {
+        path: 'Informationall',
+        component: () => import('@/views/home/Informationall.vue'),
+        name: 'homeinformationall',
+        meta: {
+          title: "个人消息",
+          icon: 'el-icon-message-solid',
+          hidden: false,
+          roles: ['admin','jerry']
+        }
+      },
+    ]
+  }
+]
+
+const router = new VueRouter({
+  mode: 'hash',
+  base: process.env.BASE_URL,
+  routes: constRouter
+})
+
+export default router
+

+ 75 - 0
src/router/permission.js

@@ -0,0 +1,75 @@
+// 路由的全局守卫
+
+// 权限控制逻辑
+import router from './index'
+import store from '../store/index'
+
+//引入nprogress 进度条插件
+import NProgress from 'nprogress'
+
+import { Message } from 'element-ui'
+import { getToken } from '@/utils/auth' // 从cookie获取令牌
+
+// 简单配置  进度条
+NProgress.inc(0.2)
+NProgress.configure({ easing: 'ease', speed: 500, showSpinner: false })
+
+
+const whiteList = ['/login'] //排除的路径
+
+router.beforeEach(async (to,from,next) => {
+    NProgress.start()
+    // 获取令牌判断用户是否登陆
+    const hasToken = getToken()
+    // 有令牌 表示已经登陆
+    if(hasToken){
+        
+        if(to.path === '/login'){
+            
+            // 已登录重定向到首页
+            next({path: '/'})
+        }else{
+            
+            //若用户角色已附加则说明动态路由已经添加
+            const hasRoles = store.getters.roles && store.getters.roles.length > 0
+
+            if(hasRoles){
+                //角色存在
+                next() //继续即可
+            } else {
+                try {
+                    //先请求获取用户角色
+                    const { roles } = await store.dispatch('user/getInfo')
+                
+                    // 根据当前用户角色动态生成路由
+                    const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
+                    
+                    // 添加这些路由至路由器
+                    router.addRoutes(accessRoutes)
+                    
+                    // 继续路由切换,确保addRoutes完成
+                    next({...to,replace: true})
+                } catch(error){
+                    // 出错需要重置令牌并重新登陆(令牌过期,网络错误等原因)
+                    await store.dispatch('user/resetToken')
+                    Message.error(error || "网络错误")
+                    next(`/login?redirect=${to.path}`)
+                }
+            }
+           
+        }
+    }else{
+        // 用户无令牌
+        if(whiteList.indexOf(to.path) !== -1){
+            //白名单路由放过
+            next()
+        } else {
+            // 重定向至登录页
+            next(`/login?redirect=${to.path}`)
+        }
+    }
+})
+
+router.afterEach(() => {
+    NProgress.done()
+  })

+ 25 - 0
src/store/index.js

@@ -0,0 +1,25 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+import permission from './modules/permission'
+import user from './modules/user'
+import tagsView from './modules/tagsView'
+Vue.use(Vuex)
+
+export default new Vuex.Store({
+  state: {
+  },
+  mutations: {
+  },
+  actions: {
+  },
+  modules: {
+    permission,
+    user,
+    tagsView
+  },
+  // 定义全局getters 方便访问user 模块的roles
+  getters:{
+    roles: state => state.user.roles,
+    permission_routes: state => state.permission.routes
+  }
+})

+ 92 - 0
src/store/modules/permission.js

@@ -0,0 +1,92 @@
+// 权限管理模块
+import { asyncRoutes, constRouter } from '@/router'
+
+/**
+ * 根据路由meta.role 确定是否当前用户拥有访问权限
+ * @roles 用户拥有角色
+ * @route 待判定路由
+ * 
+ * 
+ * 
+*/
+function hasPermission (roles,route){
+   
+    // 如果当前路由有roles 字段则需要判断用户访问权限
+    if(route.meta && route.meta.roles){
+        // 若用户拥有的角色中有被包含在待定路由角色表中的则拥有访问权限
+        return roles.some(role => route.meta.roles.includes(role))
+    } else{
+        // 没有设置roles 则无需判定即可访问
+        return true;
+    }
+}
+
+/**
+ * 递归过滤AsyncRoutes路由表
+ * @routes 待过滤路由表,首次传入的就是AsyncRoutes
+ * @roles 用户拥有角色
+ * 
+*/
+export function filterAsyncRoutes(routes,roles){
+    const res = []
+   
+    routes.forEach(route => {
+        // 复制一份
+        const tmp = { ...route}
+       
+        // 如果用户有访问权限则加入结果路由表
+        if(hasPermission(roles,tmp)){
+            // 如果存在子路由则递归过滤之
+            if(tmp.children){
+                tmp.children = filterAsyncRoutes(tmp.children,roles)
+            }
+            res.push(tmp)
+        }
+    })
+    
+    return res;
+}
+
+const state = {
+    routes: [], //完整路由表
+    addRoutes: []  //用户可访问路由表
+}
+
+const mutations = {
+    SET_ROUTES: (state, routes) => {
+        // routes 用户可以访问的权限
+        state.addRoutes = routes
+        // 完整的路由表
+        
+        state.routes = constRouter.concat(routes)
+       
+    }
+}
+
+const actions = {
+    generateRoutes({ commit }, roles) {
+        return new Promise(resolve => {
+            
+            let accessedRoutes;
+            // 用户是管理员则拥有完整访问权限
+            if(roles.includes('admin')){
+                accessedRoutes = asyncRoutes || []
+            }else{
+                // console.log(roles)
+                //  否则需要根据用户角色做过滤处理 jerry
+                accessedRoutes = filterAsyncRoutes(asyncRoutes,roles)
+            }
+          
+            commit('SET_ROUTES',accessedRoutes)
+       
+            resolve(accessedRoutes)
+        })
+    }
+}
+
+export default {
+    namespaced: true,
+    state,
+    mutations,
+    actions
+}

+ 78 - 0
src/store/modules/tagsView.js

@@ -0,0 +1,78 @@
+const tagsView = {
+  state: {
+    visitedViews: [],
+    cachedViews: []
+  },
+  mutations: {
+    ADD_VISITED_VIEWS: (state, view) => {
+      if (state.visitedViews.some(v => v.path === view.path)) return
+      state.visitedViews.push({
+        name: view.name,
+        path: view.path,
+        title: view.meta.title || 'no-name'
+      })
+      if (!view.meta.noCache) {
+        state.cachedViews.push(view.name)
+      }
+    },
+    DEL_VISITED_VIEWS: (state, view) => {
+      for (const [i, v] of state.visitedViews.entries()) {
+        if (v.path === view.path) {
+          state.visitedViews.splice(i, 1)
+          break
+        }
+      }
+      for (const i of state.cachedViews) {
+        if (i === view.name) {
+          const index = state.cachedViews.indexOf(i)
+          state.cachedViews.splice(index, 1)
+          break
+        }
+      }
+    },
+    DEL_OTHERS_VIEWS: (state, view) => {
+      for (const [i, v] of state.visitedViews.entries()) {
+        if (v.path === view.path) {
+          state.visitedViews = state.visitedViews.slice(i, i + 1)
+          break
+        }
+      }
+      for (const i of state.cachedViews) {
+        if (i === view.name) {
+          const index = state.cachedViews.indexOf(i)
+          state.cachedViews = state.cachedViews.slice(index, i + 1)
+          break
+        }
+      }
+    },
+    DEL_ALL_VIEWS: (state) => {
+      state.visitedViews = []
+      state.cachedViews = []
+    }
+  },
+  actions: {
+    addVisitedViews({ commit }, view) {
+      commit('ADD_VISITED_VIEWS', view)
+    },
+    delVisitedViews({ commit, state }, view) {
+      return new Promise((resolve) => {
+        commit('DEL_VISITED_VIEWS', view)
+        resolve([...state.visitedViews])
+      })
+    },
+    delOthersViews({ commit, state }, view) {
+      return new Promise((resolve) => {
+        commit('DEL_OTHERS_VIEWS', view)
+        resolve([...state.visitedViews])
+      })
+    },
+    delAllViews({ commit, state }) {
+      return new Promise((resolve) => {
+        commit('DEL_ALL_VIEWS')
+        resolve([...state.visitedViews])
+      })
+    }
+  }
+}
+
+export default tagsView

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

@@ -0,0 +1,62 @@
+import { getToken, setToken, removeToken } from '@/utils/auth'
+
+// 村赤用户令牌和角色信息
+const state ={
+    token: getToken(),
+    roles: [] //角色
+}
+
+const mutations ={
+    SET_TOKEN: (state,token) => {
+        state.token = token;
+    },
+    SET_ROLES: (state,roles) => {
+        state.roles = roles;
+    }
+};
+
+const actions = {
+    // 用户登录
+    login({ commit }, userInfo) {
+        const { username } = userInfo;
+        return new Promise((resolve,reject) => {
+            setTimeout(() => {
+                if(username === 'admin' || username === 'jerry'){
+                    // 保存状态
+                    commit('SET_TOKEN',username);
+                    // 写入cookie
+                    setToken(username)
+                    resolve()
+                }else{
+                    reject('用户名或密码错误')
+                }
+            },1000)
+        })
+    },
+    // 获取用户角色信息
+    getInfo({ commit, state }){
+        return new Promise((resolve) => {
+            setTimeout(() => {
+                const roles = state.token === 'admin' ? ['admin'] : ['jerry']
+                commit('SET_ROLES',roles)
+                resolve({roles})
+            },1000)
+        })
+    },
+    // 重置令牌
+    resetToken({ commit }){
+        return new Promise(resolve => {
+            commit('SET_TOKEN','')
+            commit('SET_ROLES',[])
+            removeToken();
+            resolve()
+        })
+    }
+}
+
+export default {
+    namespaced: true,
+    state,
+    mutations,
+    actions
+}

+ 15 - 0
src/utils/auth.js

@@ -0,0 +1,15 @@
+import Cookie from 'js-cookie';
+
+const Token = 'token';
+
+export function getToken(){
+    return Cookie.get(Token);
+}
+
+export function setToken(token){
+    return Cookie.set(Token,token)
+}
+
+export function removeToken(){
+    return Cookie.remove(Token)
+}

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott