Ver Fonte

初始化

luohuilong há 5 meses atrás
commit
5815a1ac35
100 ficheiros alterados com 8906 adições e 0 exclusões
  1. 5 0
      .browserslistrc
  2. 1 0
      .dockerignore
  3. 12 0
      .editorconfig
  4. 6 0
      .eslintignore
  5. 30 0
      .eslintrc.js
  6. 10 0
      .gitattributes
  7. 28 0
      .gitignore
  8. 3 0
      .stylelintrc.js
  9. 38 0
      Dockerfile
  10. 373 0
      LICENSE
  11. 43 0
      README-DCLOUD.md
  12. 323 0
      README.md
  13. 21 0
      SECURITY.md
  14. 3 0
      babel.config.js
  15. 5 0
      deploy-docker-compose.sh
  16. 7 0
      deploy-docker.sh
  17. 14 0
      docker-compose.yml
  18. 70 0
      http/mock.http
  19. 13 0
      layouts/Permissions/index.js
  20. 13 0
      layouts/Permissions/permissions.js
  21. 65 0
      layouts/VabColorfullIcon/index.vue
  22. 128 0
      layouts/VabErrorLog/index.vue
  23. 53 0
      layouts/VabFullScreenBar/index.vue
  24. 75 0
      layouts/VabGithubCorner/index.vue
  25. 20 0
      layouts/VabQueryForm/VabQueryFormBottomPanel.vue
  26. 25 0
      layouts/VabQueryForm/VabQueryFormLeftPanel.vue
  27. 25 0
      layouts/VabQueryForm/VabQueryFormRightPanel.vue
  28. 20 0
      layouts/VabQueryForm/VabQueryFormTopPanel.vue
  29. 63 0
      layouts/VabQueryForm/index.vue
  30. 69 0
      layouts/VabRemixIcon/index.vue
  31. 84 0
      layouts/VabSideBar/components/VabMenuItem.vue
  32. 108 0
      layouts/VabSideBar/components/VabSideBarItem.vue
  33. 60 0
      layouts/VabSideBar/components/VabSubmenu.vue
  34. 141 0
      layouts/VabSideBar/index.vue
  35. 293 0
      layouts/VabTabsBar/index.vue
  36. 224 0
      layouts/VabTopBar/index.vue
  37. 31 0
      layouts/index.js
  38. 5 0
      layouts/package.json
  39. 17 0
      layouts/prettier.config.js
  40. 242 0
      layouts/入口界面.html
  41. 591 0
      layouts/登录界面.html
  42. 373 0
      license.md
  43. 19 0
      mock/controller/ad.js
  44. 87 0
      mock/controller/blacklist.js
  45. 328 0
      mock/controller/colorfulIcon.js
  46. 42 0
      mock/controller/goodsDetail.js
  47. 43 0
      mock/controller/goodsList.js
  48. 989 0
      mock/controller/icon.js
  49. 51 0
      mock/controller/menuManagement.js
  50. 38 0
      mock/controller/notice.js
  51. 42 0
      mock/controller/personalCenter.js
  52. 2296 0
      mock/controller/remixIcon.js
  53. 53 0
      mock/controller/roleManagement.js
  54. 390 0
      mock/controller/router.js
  55. 88 0
      mock/controller/table.js
  56. 54 0
      mock/controller/tree.js
  57. 14 0
      mock/controller/upload.js
  58. 95 0
      mock/controller/user.js
  59. 70 0
      mock/controller/userManagement.js
  60. 98 0
      mock/index.js
  61. 94 0
      mock/mockServer.js
  62. 43 0
      mock/utils/index.js
  63. 45 0
      nginx.conf
  64. 46 0
      nginx.default.conf
  65. BIN
      node_modules.zip
  66. 109 0
      package.json
  67. 26 0
      patches/element-ui+2.15.13.patch
  68. 16 0
      prettier.config.js
  69. BIN
      public/favicon.ico
  70. BIN
      public/img/2D弹道1.png
  71. BIN
      public/img/2D弹道轨迹.jpg
  72. BIN
      public/img/banner.jpg
  73. BIN
      public/img/banner.png
  74. BIN
      public/img/dd.png
  75. BIN
      public/img/img.png
  76. BIN
      public/img/img_1.png
  77. BIN
      public/img/map.png
  78. BIN
      public/img/s01.png
  79. BIN
      public/img/s02.png
  80. BIN
      public/img/s03.png
  81. BIN
      public/img/s04.png
  82. BIN
      public/img/weixing.jpg
  83. BIN
      public/img/x01.png
  84. BIN
      public/img/x02.png
  85. BIN
      public/img/x03.png
  86. BIN
      public/img/x04.png
  87. BIN
      public/img/zha.png
  88. BIN
      public/img/zha2.png
  89. BIN
      public/img/zha3.png
  90. BIN
      public/img/zha4.png
  91. BIN
      public/img/zha5.png
  92. BIN
      public/img/态势展示.png
  93. BIN
      public/img/视角1.png
  94. BIN
      public/img/视角2.png
  95. BIN
      public/img/视角3.png
  96. BIN
      public/img/视角4.png
  97. BIN
      public/img/视角5.png
  98. BIN
      public/img/视角6.png
  99. BIN
      public/img/视角7.png
  100. BIN
      public/img/视角8.png

+ 5 - 0
.browserslistrc

@@ -0,0 +1,5 @@
+# 支持浏览器配置
+> 1%
+last 2 versions
+not dead
+

+ 1 - 0
.dockerignore

@@ -0,0 +1 @@
+node_modules

+ 12 - 0
.editorconfig

@@ -0,0 +1,12 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = false

+ 6 - 0
.eslintignore

@@ -0,0 +1,6 @@
+src/assets
+src/icons
+src/views
+public
+dist
+node_modules

+ 30 - 0
.eslintrc.js

@@ -0,0 +1,30 @@
+module.exports = {
+  root: true,
+  env: {
+    node: true,
+  },
+  extends: ["plugin:vue/recommended", "@vue/prettier"],
+  rules: {
+    "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
+    "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
+    "vue/no-v-html": "off",
+    "vue/multi-word-component-names": "off",
+    "vue/no-useless-template-attributes": "off",
+    "vue/no-reserved-component-names": "off",
+    "no-multiple-empty-lines": 0,
+  },
+  parserOptions: {
+    parser: "babel-eslint",
+  },
+  overrides: [
+    {
+      files: [
+        "**/__tests__/*.{j,t}s?(x)",
+        "**/tests/unit/**/*.spec.{j,t}s?(x)",
+      ],
+      env: {
+        jest: true,
+      },
+    },
+  ],
+};

+ 10 - 0
.gitattributes

@@ -0,0 +1,10 @@
+*.html text eol=lf
+*.css text eol=lf
+*.js text eol=lf
+*.scss text eol=lf
+*.vue text eol=lf
+*.hbs text eol=lf
+*.sh text eol=lf
+*.md text eol=lf
+*.json text eol=lf
+*.yml text eol=lf

+ 28 - 0
.gitignore

@@ -0,0 +1,28 @@
+.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
+.gradle
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw*
+package-lock.json
+pnpm-lock.yaml
+
+### script ###
+/git-pull.sh
+/git-push.sh

+ 3 - 0
.stylelintrc.js

@@ -0,0 +1,3 @@
+module.exports = {
+  extends: ["stylelint-config-recess-order", "stylelint-config-prettier"],
+};

+ 38 - 0
Dockerfile

@@ -0,0 +1,38 @@
+FROM nginx
+
+MAINTAINER opsli.com
+LABEL version=V1.3.3
+LABEL description=OPSLI-快速开发平台
+LABEL qqGroup=724850675
+
+# 环境变量
+ENV TZ=Asia/Shanghai \
+    RUN_USER=nginx \
+    RUN_GROUP=nginx \
+    DATA_DIR=/data/web \
+    LOG_DIR=/data/log/nginx
+
+# 工作目录
+WORKDIR ${DATA_DIR}
+
+# 日志输出
+RUN ["echo","XX系统 - UI building..."]
+
+# 切换为上海时区
+RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime \
+    && echo $TZ > /etc/timezone
+
+# 创建日志文件夹
+RUN mkdir ${LOG_DIR} -p
+RUN chown nginx.nginx -R ${LOG_DIR}
+
+# 拷贝dist包文件
+COPY ./dist ./
+
+# 拷贝nginx配置文件
+ADD nginx.conf /etc/nginx/nginx.conf
+ADD nginx.default.conf /etc/nginx/conf.d/default.conf
+
+EXPOSE 80
+
+ENTRYPOINT nginx -g "daemon off;"

+ 373 - 0
LICENSE

@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  This Source Code Form is subject to the terms of the Mozilla Public
+  License, v. 2.0. If a copy of the MPL was not distributed with this
+  file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+  This Source Code Form is "Incompatible With Secondary Licenses", as
+  defined by the Mozilla Public License, v. 2.0.

+ 43 - 0
README-DCLOUD.md

@@ -0,0 +1,43 @@
+<div align="center"><img width="200" src="https://gitee.com/chu1204505056/vue-admin-beautiful/raw/master/src/colorfulIcon/svg/vab.svg"/>
+<h1> vue-admin-beautiful </h1>
+<h3>一款基于 vue+element-ui 的绝佳的通用型、中后台前端框架</h3>
+<h3>An excellent general-purpose, middle and background front-end framework based on Vue + element UI</h3>
+</div>
+
+[![](https://img.shields.io/github/stars/chuzhixin/vue-admin-beautiful?style=flat-square&label=Stars&logo=github)
+](https://github.com/chuzhixin/vue-admin-beautiful)
+
+## 演示地址
+
+### - [🚀 演示地址:vue-admin-beautiful (横向纵向布局无缝切换)](https://chu1204505056.gitee.io/vue-admin-beautiful/?hmsr=%E6%8F%92%E4%BB%B6%E5%B8%82%E5%9C%BA&hmpl=&hmcu=&hmkw=&hmci=)
+
+### - [🚀 vue-admin-beautiful-pro 版演示地址](https://chu1204505056.gitee.io/vue-admin-beautiful-pro/?hmsr=%E6%8F%92%E4%BB%B6%E5%B8%82%E5%9C%BA&hmpl=&hmcu=&hmkw=&hmci=)
+
+### - [🚀 vue-admin-beautiful-mini vue3.0 预览版地址](https://chu1204505056.gitee.io/vue-admin-beautiful-mini/?hmsr=%E6%8F%92%E4%BB%B6%E5%B8%82%E5%9C%BA&hmpl=&hmcu=&hmkw=&hmci=)
+
+## vue-admin-beautiful 前端讨论群-1 972435319
+
+不管您加或者不加,您都可以享受到开源的代码,感谢您的支持和信任,群内提供 vue-admin-beautiful-template 基础版本和详细的基础使用文档适合框架快速入门
+
+![img](https://chu1204505056.gitee.io/vabBooks/img/ewm.png)
+
+## 安装
+
+```bash
+# 克隆项目
+git clone https://github.com/chuzhixin/vue-admin-beautiful.git
+# 进入项目目录
+npm vue-admin-beautiful
+# 安装依赖
+npm i
+# 本地开发 启动项目
+cnpm run serve
+```
+
+#### github 标星增长量统计
+
+[![Stargazers over time](https://starcharts.herokuapp.com/chuzhixin/vue-admin-beautiful.svg)](https://github.com/chuzhixin/vue-admin-beautiful)
+
+#### 开发者评级
+
+[![chuzhixin's github stats](https://github-readme-stats.vercel.app/api?username=chuzhixin)](https://github.com/chuzhixin/vue-admin-beautiful)

+ 323 - 0
README.md

@@ -0,0 +1,323 @@
+#
+
+<div align="center"><img width="200" src="https://gitee.com/chu1204505056/vue-admin-beautiful/raw/master/src/colorfulIcon/svg/vab.svg"/>
+<h1> vue-admin-beautiful </h1>
+<h3>一款基于 vue+element-ui 的绝佳的通用型、中后台前端框架</h3>
+<h3>An excellent general-purpose, middle and background front-end framework based on Vue + element UI</h3>
+</div>
+
+![image](https://repository-images.githubusercontent.com/249342059/8ff9d000-bef5-11ea-837f-8c265b79e3db)
+
+## vue-admin-beautiful 前端讨论群-1 972435319
+
+不管您加或者不加,您都可以享受到开源的代码,感谢您的支持和信任,群内提供 vue-admin-beautiful-template 基础版本和详细的基础使用文档适合框架快速入门
+
+![img](https://gitee.com/chu1204505056/vabBooks/raw/gh-pages/img/ewm.png)
+
+## 🎉🎉🎉 基于 vue3.0 的 vue-admin-beautiful-mini 正在快马加鞭的开发,敬请期待!!!
+
+## 地址
+
+### - [🎉 演示地址 1:vue-admin-beautiful](http://beautiful.panm.cn/vue-admin-beautiful/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
+
+### - [🎉 演示地址 2:vue-admin-beautiful:vue-admin-beautiful](https://chu1204505056.gitee.io/vue-admin-beautiful/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
+
+### - [🚀 pro 版演示地址 1:vue-admin-beautiful-pro](http://beautiful.panm.cn/vue-admin-beautiful-pro/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
+
+### - [🚀 pro 版演示地址 2:vue-admin-beautiful-pro](https://chu1204505056.gitee.io/vue-admin-beautiful-pro/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
+
+### - [🌐 github 仓库地址](https://github.com/chuzhixin/vue-admin-beautiful/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
+
+### - [🌐 码云仓库地址](https://gitee.com/chu1204505056/vue-admin-beautiful/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
+
+### - [🌐 vue3.0 版本研发进度展示(基础版本已全部贯通、适配电脑、手机、平板)](https://chu1204505056.gitee.io/vue-admin-beautiful-mini/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
+
+## 安装
+
+```bash
+# 克隆项目
+git clone https://github.com/chuzhixin/vue-admin-beautiful.git
+# 进入项目目录
+cd vue-admin-beautiful
+# 安装依赖
+npm i
+# 本地开发 启动项目
+npm run serve
+```
+
+## install
+
+```bash
+# Clone project
+git clone https://github.com/chuzhixin/vue-admin-beautiful.git
+# Enter project directory
+cd vue-admin-beautiful
+# Installation dependency
+npm i
+# Start project
+npm run serve
+```
+
+## 友情链接
+
+### - [uView 文档(超棒的移动跨端框架,文档详细,上手容易)](https://uviewui.com/)
+
+### - [Element UI 表单设计及代码生成器(可视化表单设计器,一键生成 element 表单)](https://github.com/JakHuang/form-generator/)
+
+### - [luch-request(基于 Promise 开发的 uni-app 跨平台、项目级别的请求库,它有更小的体积,易用的 api,方便简单的自定义能力)](https://www.quanzhan.co/luch-request/)
+
+### - [umyui 文档(开发者准备的基于 Vue 2.0 的桌面端组件库; 流畅渲染表格万级数据)](http://www.umyui.com/)
+
+## setting.js 配置
+
+- 说明:这里有好多你会用到的配置项。
+- 位置:src/config/settings.js
+- 注意:此处可能不是最新代码具体可查看[github 最新的 settings.js 配置](https://github.com/chuzhixin/vue-admin-beautiful/blob/master/src/config/settings.js)
+- 示例代码:
+
+```js
+/**
+ * @copyright chuzhixin 1204505056@qq.com
+ * @description 全局变量配置
+ */
+module.exports = {
+  // 开发以及部署时的URL
+  publicPath: "",
+  // 生产环境构建文件的目录名
+  outputDir: "dist",
+  // 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。
+  assetsDir: "static",
+  // 开发环境每次保存时是否输出为eslint编译警告
+  lintOnSave: true,
+  // 进行编译的依赖
+  transpileDependencies: ["vue-echarts", "resize-detector", "zx-layouts"],
+  // 默认的接口地址 如果是开发环境和生产环境走vab-mock-server,当然你也可以选择自己配置成需要的接口地址
+  baseURL:
+    process.env.NODE_ENV === "development"
+      ? "vab-mock-server"
+      : "vab-mock-server",
+  //标题 (包括初次加载雪花屏的标题 页面的标题 浏览器的标题)
+  title: "vue-admin-beautiful",
+  //简写
+  abbreviation: "vab",
+  //开发环境端口号
+  devPort: "80",
+  //版本号
+  version: process.env.VUE_APP_VERSION,
+  //烦请保留package.json作者信息 保留版权可免费商用
+  copyright: process.env.VUE_APP_AUTHOR,
+  //是否显示页面底部版权信息,建议您显示,当然您也可以选择不显示,不管您是付费用户还是未付费用户您都有选择显示或者不显示的权利
+  footerCopyright: process.env.NODE_ENV !== "development" ? true : false,
+  //是否显示右上角github图标
+  githubCorner: process.env.NODE_ENV !== "development" ? true : false,
+  //是否显示顶部进度条
+  progressBar: true,
+  //缓存路由的最大数量
+  keepAliveMaxNum: 99,
+  // 路由模式,可选值为 history 或 hash
+  routerMode: "hash",
+  //不经过token校验的路由
+  routesWhiteList: ["/login", "/register", "/404", "/401"],
+  //加载时显示文字
+  loadingText: "正在加载中...",
+  //token名称
+  tokenName: "accessToken",
+  //token在localStorage、sessionStorage、cookie存储的key的名称
+  tokenTableName: "vue-admin-beautiful",
+  //token存储位置localStorage sessionStorage cookie
+  storage: "localStorage",
+  //token失效回退到登录页时是否记录本次的路由
+  recordRoute: true,
+  //是否显示logo,不显示时设置false,显示时请填写remixIcon图标名称,暂时只支持设置remixIcon
+  logo: "vuejs-fill",
+  //是否国定头部 固定fixed 不固定noFixed
+  header: "fixed",
+  //横纵布局 horizontal vertical
+  layout: "vertical",
+  //是否开启主题配置按钮
+  themeBar: true,
+  //是否显示多标签页
+  tagsBar: true,
+  //是否显示骨架屏
+  skeleton: false,
+  //配后端数据的接收方式application/json;charset=UTF-8或者application/x-www-form-urlencoded;charset=UTF-8
+  contentType: "application/json;charset=UTF-8",
+  //消息框消失时间
+  messageDuration: 3000,
+  //最长请求时间
+  requestTimeout: 5000,
+  //操作正常code
+  successCode: 200,
+  //登录失效code
+  invalidCode: 402,
+  //无权限code
+  noPermissionCode: 401,
+  //是否显示在页面高亮错误
+  errorLog: ["development", "test", "production"],
+  //是否开启登录拦截
+  loginInterception: true,
+  //部分接口是否开启RSA加密
+  encryptRSA: false,
+  //是否依据mock数据生成webstorm HTTP Request请求文件
+  httpRequestFile: false,
+  //intelligence和all两种方式,前者后端权限只控制permissions不控制view文件的import(前后端配合,减轻后端工作量),all方式完全交给后端前端只负责加载
+  authentication: "intelligence",
+  //vertical布局时是否只保持一个子菜单的展开
+  uniqueOpened: true,
+  //vertical布局时默认展开的菜单path,使用逗号隔开建议只展开一个
+  defaultOopeneds: ["/vab"],
+  //需要加loading层的请求,防止重复提交
+  debounce: ["doEdit"],
+  //需要自动注入并加载的模块
+  providePlugin: { maptalks: "maptalks", "window.maptalks": "maptalks" },
+  //npm run build时是否自动生成7z压缩包
+  build7z: false,
+  //npm run build时是否自动压缩图片 国内网络不好的情况下可以关闭压缩图片
+  imageCompression: false,
+  //代码生成机生成在view下的文件夹名称
+  templateFolder: "project",
+};
+```
+
+## variables.scss 配置
+
+- 说明:这里可以修改你项目的配色方案,简单修改即可实现风格大变。
+- 位置:src/styles/variables.scss
+- 注意:此处可能不是最新代码具体可查看[github 最新的 variables.scss 配置](https://github.com/chuzhixin/vue-admin-beautiful/blob/master/src/styles/variables.scss)
+
+```scss
+/**
+ * @copyright chuzhixin 1204505056@qq.com
+ * @description 全局主题变量配置,VIP文档内提供多种好看的配色方案(ant-design风格、layui风格、iview风格),请查看VIP文档主题配置篇
+ */
+/* stylelint-disable */
+@charset "utf-8";
+//框架默认主题色
+$base-color-default: #1890ff;
+//默认层级
+$base-z-index: 999;
+//横向布局纵向布局时菜单背景色
+$base-menu-background: #001529;
+//菜单文字颜色
+$base-menu-color: hsla(0, 0%, 100%, 0.95);
+//菜单选中文字颜色
+$base-menu-color-active: hsla(0, 0%, 100%, 0.95);
+//菜单选中背景色
+$base-menu-background-active: $base-color-default;
+//标题颜色
+$base-title-color: #fff;
+//字体大小配置
+$base-font-size-small: 12px;
+$base-font-size-default: 14px;
+$base-font-size-big: 16px;
+$base-font-size-bigger: 18px;
+$base-font-size-max: 22px;
+$base-font-color: #606266;
+$base-color-blue: $base-color-default;
+$base-color-green: #13ce66;
+$base-color-white: #fff;
+$base-color-black: #000;
+$base-color-yellow: #ffba00;
+$base-color-orange: #ff6700;
+$base-color-red: #ff4d4f;
+$base-color-gray: rgba(0, 0, 0, 0.65);
+$base-main-width: 1279px;
+$base-border-radius: 2px;
+$base-border-color: #dcdfe6;
+//输入框高度
+$base-input-height: 32px;
+//默认paddiing
+$base-padding: 20px;
+//默认阴影
+$base-box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
+//横向布局时top-bar、logo、一级菜单的高度
+$base-top-bar-height: 65px;
+//纵向布局时logo的高度
+$base-logo-height: 75px;
+//顶部nav-bar的高度
+$base-nav-bar-height: 60px;
+//顶部多标签页tags-bar的高度
+$base-tags-bar-height: 55px;
+//顶部多标签页tags-bar中每一个item的高度
+$base-tag-item-height: 34px;
+//菜单li标签的高度
+$base-menu-item-height: 50px;
+//app-main的高度
+$base-app-main-height: calc(
+  100vh - #{$base-nav-bar-height} - #{$base-tags-bar-height} -
+    #{$base-padding} - #{$base-padding} - 55px - 30px
+);
+//纵向布局时左侧导航未折叠时的宽度
+$base-left-menu-width: 230px;
+//纵向布局时左侧导航未折叠时右侧内容的宽度
+$base-right-content-width: calc(100% - #{$base-left-menu-width});
+//纵向布局时左侧导航已折叠时的宽度
+$base-left-menu-width-min: 65px;
+//纵向布局时左侧导航已折叠时右侧内容的宽度
+$base-right-content-width-min: calc(100% - #{$base-left-menu-width-min});
+//默认动画
+$base-transition: all 0.2s;
+//默认动画时长
+$base-transition-time: 0.2s;
+
+:export {
+  //菜单文字颜色变量导出
+  menu-color: $base-menu-color;
+  //菜单选中文字颜色变量导出
+  menu-color-active: $base-menu-color-active;
+  //菜单背景色变量导出
+  menu-background: $base-menu-background;
+  //菜单选中背景色变量导出
+  menu-background-active: $base-menu-background-active;
+  //多标签页选中背景色变量导出
+  tag-background-active: $base-color-blue;
+  //默认按钮背景色变量导出
+  button-background: $base-color-blue;
+  //分页选中背景色变量导出
+  pagination-background-active: $base-color-blue;
+}
+```
+
+## element-ui 组件尺寸配置
+
+- 说明:这里可以修改你 element-ui 组件尺寸,element-ui 组件的尺寸一共分为 large、default、small 、mini,本项目默认使用的是 small。
+- 位置:src/plugins/element.js
+- 示例代码:
+
+```js
+import Vue from "vue";
+import ElementUI from "element-ui";
+import "element-ui/lib/theme-chalk/display.css";
+
+import "@/styles/element-variables.scss";
+
+Vue.use(ElementUI, {
+  size: "small", // element-ui组件的尺寸一共分为large、default、small 、mini
+});
+```
+
+## 付费技术支持,商务合作
+
+### 联系:QQ 1204505056
+
+## 捐赠
+
+![img](https://chu1204505056.gitee.io/vabBooks/img/donation.png)
+
+#### github 标星增长量统计
+
+[![Stargazers over time](https://starcharts.herokuapp.com/chuzhixin/vue-admin-beautiful.svg)](https://github.com/chuzhixin/vue-admin-beautiful)
+
+#### 开发者评级
+
+[![chuzhixin's github stats](https://github-readme-stats.vercel.app/api?username=chuzhixin)](https://github.com/chuzhixin/vue-admin-beautiful)
+
+## 关于框架的声明
+
+框架在保留作者版权信息的前提下可免费用于商业使用,框架所有代码包含 npm 包中的源码内容均为免费开放,如果您愿意支持我、或者希望完全变成自己的版权信息,需支付 299 元,如果您愿意加入 VIP 群学习需支付 100 元,这一切都是在您自愿的基础上,如果您觉得框架一文不值,请直接略过,高抬贵手放我一马,不要恶意刷差评,希望每个使用 vue-admin-beautiful 的人无论过程怎样,结局都是美好的,联系方式 QQ 1204505056
+
+## vue-admin-beautiful 前端讨论群-2 1139183756
+
+不管您加或者不加,您都可以享受到开源的代码,感谢您的支持和信任,群内提供 vue-admin-beautiful-template 基础版本和详细的基础使用文档适合框架快速入门
+
+![img](https://gitee.com/chu1204505056/vabBooks/raw/gh-pages/img/ewm_2.png)

+ 21 - 0
SECURITY.md

@@ -0,0 +1,21 @@
+# Security Policy
+
+## Supported Versions
+
+Use this section to tell people about which versions of your project are
+currently being supported with security updates.
+
+| Version | Supported          |
+| ------- | ------------------ |
+| 5.1.x   | :white_check_mark: |
+| 5.0.x   | :x:                |
+| 4.0.x   | :white_check_mark: |
+| < 4.0   | :x:                |
+
+## Reporting a Vulnerability
+
+Use this section to tell people how to report a vulnerability.
+
+Tell them where to go, how often they can expect to get an update on a
+reported vulnerability, what to expect if the vulnerability is accepted or
+declined, etc.

+ 3 - 0
babel.config.js

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

+ 5 - 0
deploy-docker-compose.sh

@@ -0,0 +1,5 @@
+#!/bin/bash
+
+npm run build
+
+docker-compose up -d

+ 7 - 0
deploy-docker.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+npm run build
+
+docker build -t opsli-ui .
+
+docker run --name opsli-ui --restart=always -p 80:80 -v /var/nginx:/var/data -d opsli-ui

+ 14 - 0
docker-compose.yml

@@ -0,0 +1,14 @@
+version: '3.3'
+services:
+  opsli-ui:
+    build: ./
+    restart: always
+    container_name: opsli-ui
+    image: opsli-ui
+    environment:
+      TZ: Asia/Shanghai
+      LANG: en_US.UTF-8
+    volumes:
+      - /var/nginx:/var/data #挂载 Nginx 文件
+    ports:
+      - "80:80"

+ 70 - 0
http/mock.http

@@ -0,0 +1,70 @@
+
+###/changeLog/getList###mockServer
+POST http://localhost:80/mock-server/changeLog/getList
+Content-Type: application/x-www-form-urlencoded
+###
+mockServer
+###/colorfulIcon/list###
+POST http://localhost:80/mock-server/colorfulIcon/list
+Content-Type: application/x-www-form-urlencoded
+###mockServer
+
+###/menu/navigate###
+POST http://localhost:80/mock-server/menu/navigate
+Content-Type: application/x-www-form-urlenmockServer
+###
+
+###/icon/list###
+POST http://localhost:80/mock-server/icon/mockServer
+Content-Type: application/x-www-form-urlencoded
+###
+
+###/face/list###mockServer
+POST http://localhost:80/mock-server/face/list
+Content-Type: application/x-www-form-urlencoded
+###
+mockServer
+###/table/list###
+POST http://localhost:80/mock-server/table/list
+Content-Type: application/x-www-form-urlencoded
+###mockServer
+
+###/remixicon/getList###
+POST http://localhost:80/mock-server/remixicon/getList
+Content-Type: application/x-www-form-urlenmockServer
+###
+
+###/publicKey###
+POST http://localhost:80/mock-server/pumockServer
+Content-Type: application/x-www-form-urlencoded
+###
+
+###/tree/list###mockServer
+POST http://localhost:80/mock-server/tree/list
+Content-Type: application/x-www-form-urlencoded
+###
+mockServer
+###/upload###
+POST http://localhost:80/mock-server/upload
+Content-Type: application/x-www-form-urlencoded
+###mockServer
+
+###/login###
+POST http://localhost:80/mock-server/login
+Content-Type: application/x-www-form-urlenmockServer
+###
+
+###/waterfall/list###
+POST http://localhost:80/mock-server/waterfall/list
+Content-Type: application/x-www-form-urlencoded
+###
+
+###/logout###
+POST http://localhost:80/mock-server/logout
+Content-Type: application/x-www-form-urlencoded
+###
+
+###/userInfo###
+POST http://localhost:80/mock-server/userInfo
+Content-Type: application/x-www-form-urlencoded
+###

+ 13 - 0
layouts/Permissions/index.js

@@ -0,0 +1,13 @@
+import permissions from './permissions'
+
+const install = function (Vue) {
+  Vue.directive('permissions', permissions)
+}
+
+if (window.Vue) {
+  window['permissions'] = permissions
+  Vue.use(install)
+}
+
+permissions.install = install
+export default permissions

+ 13 - 0
layouts/Permissions/permissions.js

@@ -0,0 +1,13 @@
+import store from '@/store'
+
+export default {
+  inserted(element, binding) {
+    const { value } = binding
+    const permissions = store.getters['user/permissions']
+    if (value && value instanceof Array && value.length > 0) {
+      const hasPermission = permissions.some((role) => value.includes(role))
+      if (!hasPermission)
+        element.parentNode && element.parentNode.removeChild(element)
+    }
+  },
+}

+ 65 - 0
layouts/VabColorfullIcon/index.vue

@@ -0,0 +1,65 @@
+<template>
+  <img
+    v-if="isExternal"
+    :src="styleExternalIcon"
+    class="svg-external-icon svg-icon"
+    v-on="$listeners"
+  />
+  <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
+    <use :xlink:href="iconName" />
+  </svg>
+</template>
+
+<script>
+  import { isExternal } from '@/utils/validate'
+
+  export default {
+    name: 'VabColorfulIcon',
+    props: {
+      iconClass: {
+        type: String,
+        required: true,
+      },
+      className: {
+        type: String,
+        default: '',
+      },
+    },
+    computed: {
+      isExternal() {
+        return isExternal(this.iconClass)
+      },
+      iconName() {
+        return `#colorful-icon-${this.iconClass}`
+      },
+      svgClass() {
+        if (this.className) {
+          return 'svg-icon ' + this.className
+        } else {
+          return 'svg-icon'
+        }
+      },
+      styleExternalIcon() {
+        return this.iconClass
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  .svg-icon {
+    width: 1em;
+    height: 1em;
+    overflow: hidden;
+    vertical-align: -0.15em;
+    fill: currentColor;
+
+    &:hover {
+      opacity: 0.8;
+    }
+  }
+
+  .svg-external-icon {
+    display: inline-block;
+  }
+</style>

+ 128 - 0
layouts/VabErrorLog/index.vue

@@ -0,0 +1,128 @@
+<template>
+  <div v-if="errorLogs.length > 0">
+    <el-badge
+      :value="errorLogs.length"
+      @click.native="dialogTableVisible = true"
+    >
+      <el-button type="danger">
+        <vab-icon :icon="['fas', 'bug']" />
+      </el-button>
+    </el-badge>
+
+    <el-dialog
+      :visible.sync="dialogTableVisible"
+      append-to-body
+      width="70%"
+      title="OPSLI 异常捕获(温馨提示:错误必须解决)"
+    >
+      <el-table :data="errorLogs">
+        <el-table-column label="报错路由">
+          <template slot-scope="{ row }">
+            <a :href="row.url" target="_blank">
+              <el-tag type="success">{{ row.url }}</el-tag>
+            </a>
+          </template>
+        </el-table-column>
+        <el-table-column label="错误信息">
+          <template slot-scope="{ row }">
+            <el-tag type="danger">{{ decodeUnicode(row.err.message) }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="错误详情" width="120">
+          <template slot-scope="scope">
+            <el-popover placement="top-start" trigger="hover">
+              <div style="color: red">
+                {{ scope.row.err.stack }}
+              </div>
+              <el-button slot="reference">查看</el-button>
+            </el-popover>
+          </template>
+        </el-table-column>
+        <el-table-column width="380" label="操作">
+          <template slot-scope="{ row }">
+            <a
+              v-for="(item, index) in searchList"
+              :key="index"
+              :href="item.url + decodeUnicode(row.err.message)"
+              target="_blank"
+            >
+              <el-button style="margin-left: 5px" type="primary">
+                <vab-icon :icon="['fas', 'search']" />
+                {{ item.title }}
+              </el-button>
+            </a>
+          </template>
+        </el-table-column>
+      </el-table>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogTableVisible = false">取 消</el-button>
+        <el-button type="danger" icon="el-icon-delete" @click="clearAll">
+          暂不显示
+        </el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+  import { abbreviation, title } from '@/config'
+  import { mapGetters } from 'vuex'
+
+  export default {
+    name: 'VabErrorLog',
+
+    data() {
+      return {
+        dialogTableVisible: false,
+        title: title,
+        abbreviation: abbreviation,
+        searchList: [
+          {
+            title: '百度搜索',
+            url: 'https://www.baidu.com/baidu?wd=',
+          },
+          {
+            title: '谷歌搜索',
+            url: 'https://www.google.com/search?q=',
+          },
+          {
+            title: 'Magi搜索',
+            url: 'https://magi.com/search?q=',
+          },
+        ],
+      }
+    },
+
+    computed: {
+      ...mapGetters({
+        errorLogs: 'errorLog/errorLogs',
+      }),
+    },
+    methods: {
+      clearAll() {
+        this.dialogTableVisible = false
+        this.$store.dispatch('errorLog/clearErrorLog')
+      },
+      decodeUnicode(str) {
+        str = str.replace(/\\/g, '%')
+        str = unescape(str)
+        str = str.replace(/%/g, '\\')
+        str = str.replace(/\\/g, '')
+        return str
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  ::v-deep {
+    .el-badge {
+      .el-button {
+        height: 28px;
+        display: flex;
+        justify-items: center;
+        align-items: center;
+      }
+    }
+  }
+</style>

+ 53 - 0
layouts/VabFullScreenBar/index.vue

@@ -0,0 +1,53 @@
+<template>
+  <span :title="isFullscreen ? '退出全屏' : '进入全屏'">
+    <vab-icon
+      :icon="[
+        'fas',
+        isFullscreen ? 'compress-arrows-alt' : 'expand-arrows-alt',
+      ]"
+      @click="click"
+    ></vab-icon>
+  </span>
+</template>
+
+<script>
+  import screenfull from 'screenfull'
+
+  export default {
+    name: 'VabFullScreenBar',
+    data() {
+      return {
+        isFullscreen: false,
+      }
+    },
+    mounted() {
+      this.init()
+    },
+    beforeDestroy() {
+      this.destroy()
+    },
+    methods: {
+      click() {
+        if (!screenfull.isEnabled) {
+          this.$baseMessage('开启全屏失败', 'error')
+          return false
+        }
+        screenfull.toggle()
+        this.$emit('refresh')
+      },
+      change() {
+        this.isFullscreen = screenfull.isFullscreen
+      },
+      init() {
+        if (screenfull.isEnabled) {
+          screenfull.on('change', this.change)
+        }
+      },
+      destroy() {
+        if (screenfull.isEnabled) {
+          screenfull.off('change', this.change)
+        }
+      },
+    },
+  }
+</script>

+ 75 - 0
layouts/VabGithubCorner/index.vue

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

+ 20 - 0
layouts/VabQueryForm/VabQueryFormBottomPanel.vue

@@ -0,0 +1,20 @@
+<template>
+  <el-col :span="24">
+    <div class="bottom-panel">
+      <slot></slot>
+    </div>
+  </el-col>
+</template>
+
+<script>
+  export default {
+    name: "VabQueryFormBottomPanel",
+    props: {},
+    data() {
+      return {};
+    },
+    created() {},
+    mounted() {},
+    methods: {},
+  };
+</script>

+ 25 - 0
layouts/VabQueryForm/VabQueryFormLeftPanel.vue

@@ -0,0 +1,25 @@
+<template>
+  <el-col :xs="24" :sm="24" :md="24" :lg="span" :xl="span">
+    <div class="left-panel">
+      <slot></slot>
+    </div>
+  </el-col>
+</template>
+
+<script>
+  export default {
+    name: 'VabQueryFormLeftPanel',
+    props: {
+      span: {
+        type: Number,
+        default: 14,
+      },
+    },
+    data() {
+      return {}
+    },
+    created() {},
+    mounted() {},
+    methods: {},
+  }
+</script>

+ 25 - 0
layouts/VabQueryForm/VabQueryFormRightPanel.vue

@@ -0,0 +1,25 @@
+<template>
+  <el-col :xs="24" :sm="24" :md="24" :lg="span" :xl="span">
+    <div class="right-panel">
+      <slot></slot>
+    </div>
+  </el-col>
+</template>
+
+<script>
+  export default {
+    name: 'VabQueryFormRightPanel',
+    props: {
+      span: {
+        type: Number,
+        default: 10,
+      },
+    },
+    data() {
+      return {}
+    },
+    created() {},
+    mounted() {},
+    methods: {},
+  }
+</script>

+ 20 - 0
layouts/VabQueryForm/VabQueryFormTopPanel.vue

@@ -0,0 +1,20 @@
+<template>
+  <el-col :span="24">
+    <div class="top-panel">
+      <slot></slot>
+    </div>
+  </el-col>
+</template>
+
+<script>
+  export default {
+    name: 'VabQueryFormTopPanel',
+    props: {},
+    data() {
+      return {}
+    },
+    created() {},
+    mounted() {},
+    methods: {},
+  }
+</script>

+ 63 - 0
layouts/VabQueryForm/index.vue

@@ -0,0 +1,63 @@
+<template>
+  <el-row :gutter="0" class="vab-query-form">
+    <slot></slot>
+  </el-row>
+</template>
+
+<script>
+  export default {
+    name: 'VabQueryForm',
+    props: {},
+    data() {
+      return {}
+    },
+    created() {},
+    mounted() {},
+    methods: {},
+  }
+</script>
+
+<style lang="scss" scoped>
+  @mixin panel {
+    display: flex;
+    flex-wrap: wrap;
+    align-items: center;
+    justify-content: flex-start;
+  }
+
+  .vab-query-form {
+    margin-bottom: 10px;
+
+    ::v-deep {
+      .top-panel {
+        @include panel;
+      }
+
+      .bottom-panel {
+        @include panel;
+
+        padding-top: 14px;
+        border-top: 1px solid #dcdfe6;
+      }
+
+      .left-panel {
+        @include panel;
+
+        > .el-button,
+        .el-form-item {
+          margin: 5px;
+        }
+      }
+
+      .right-panel {
+        @include panel;
+
+        justify-content: flex-end;
+
+        .el-form-item {
+          margin: 5px;
+        }
+      }
+    }
+  }
+</style>

+ 69 - 0
layouts/VabRemixIcon/index.vue

@@ -0,0 +1,69 @@
+<template>
+  <div
+    v-if="isExternal"
+    :style="styleExternalIcon"
+    class="svg-external-icon svg-icon"
+    v-on="$listeners"
+  />
+  <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
+    <use :xlink:href="iconName" />
+  </svg>
+</template>
+
+<script>
+  import { isExternal } from '@/utils/validate'
+
+  export default {
+    name: 'VabRemixIcon',
+    props: {
+      iconClass: {
+        type: String,
+        required: true,
+      },
+      className: {
+        type: String,
+        default: '',
+      },
+    },
+    computed: {
+      isExternal() {
+        return isExternal(this.iconClass)
+      },
+      iconName() {
+        return `#remix-icon-${this.iconClass}`
+      },
+      svgClass() {
+        if (this.className) {
+          return 'svg-icon ' + this.className
+        } else {
+          return 'svg-icon'
+        }
+      },
+      styleExternalIcon() {
+        return {
+          mask: `url(${this.iconClass}) no-repeat 50% 50%`,
+          '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`,
+        }
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  .svg-icon {
+    width: 1.125em;
+    height: 1.125em;
+    overflow: hidden;
+    fill: currentColor;
+
+    &:hover {
+      opacity: 0.8;
+    }
+  }
+
+  .svg-external-icon {
+    display: inline-block;
+    background-color: currentColor;
+    mask-size: cover !important;
+  }
+</style>

+ 84 - 0
layouts/VabSideBar/components/VabMenuItem.vue

@@ -0,0 +1,84 @@
+<template>
+  <el-menu-item :index="handlePath(routeChildren.path)" @click="handleLink">
+    <vab-icon
+      v-if="routeChildren.meta.icon"
+      :icon="['fas', routeChildren.meta.icon]"
+      class="vab-fas-icon"
+    />
+    <span>{{ routeChildren.meta.title }}</span>
+    <el-tag
+      v-if="routeChildren.meta && routeChildren.meta.badge"
+      type="danger"
+      effect="dark"
+    >
+      {{ routeChildren.meta.badge }}
+    </el-tag>
+  </el-menu-item>
+</template>
+
+<script>
+  import { isExternal } from '@/utils/validate'
+  import path from 'path'
+
+  export default {
+    name: 'VabMenuItem',
+    props: {
+      routeChildren: {
+        type: Object,
+        default() {
+          return null
+        },
+      },
+      item: {
+        type: Object,
+        default() {
+          return null
+        },
+      },
+      fullPath: {
+        type: String,
+        default: '',
+      },
+    },
+    methods: {
+      handlePath(routePath) {
+        if (isExternal(routePath)) {
+          return routePath
+        }
+        if (isExternal(this.fullPath)) {
+          return this.fullPath
+        }
+        return path.resolve(this.fullPath, routePath)
+      },
+      handleLink() {
+        const routePath = this.routeChildren.path
+        const target = this.routeChildren.meta.target
+
+        if (target === '_blank') {
+          if (isExternal(routePath)) {
+            window.open(routePath)
+          } else if (isExternal(this.fullPath)) {
+            window.open(this.fullPath)
+          } else if (
+            this.$route.path !== path.resolve(this.fullPath, routePath)
+          ) {
+            let routeData = this.$router.resolve(
+              path.resolve(this.fullPath, routePath)
+            )
+            window.open(routeData.href)
+          }
+        } else {
+          if (isExternal(routePath)) {
+            window.location.href = routePath
+          } else if (isExternal(this.fullPath)) {
+            window.location.href = this.fullPath
+          } else if (
+            this.$route.path !== path.resolve(this.fullPath, routePath)
+          ) {
+            this.$router.push(path.resolve(this.fullPath, routePath))
+          }
+        }
+      },
+    },
+  }
+</script>

+ 108 - 0
layouts/VabSideBar/components/VabSideBarItem.vue

@@ -0,0 +1,108 @@
+<template>
+  <component
+    :is="menuComponent"
+    v-if="!item.hidden"
+    :item="item"
+    :full-path="fullPath"
+    :route-children="routeChildren"
+  >
+    <template v-if="item.children && item.children.length">
+      <vab-side-bar-item
+        v-for="route in item.children"
+        :key="route.path"
+        :full-path="handlePath(route.path)"
+        :item="route"
+      />
+    </template>
+  </component>
+</template>
+
+<script>
+  import { isExternal } from '@/utils/validate'
+  import path from 'path'
+
+  export default {
+    name: 'VabSideBarItem',
+    props: {
+      item: {
+        type: Object,
+        required: true,
+      },
+      fullPath: {
+        type: String,
+        default: '',
+      },
+    },
+    data() {
+      this.onlyOneChild = null
+      return {}
+    },
+    computed: {
+      menuComponent() {
+        if (
+          this.handleChildren(this.item.children, this.item) &&
+          (!this.routeChildren.children ||
+            this.routeChildren.notShowChildren) &&
+          !this.item.alwaysShow
+        ) {
+          return 'VabMenuItem'
+        } else {
+          return 'VabSubmenu'
+        }
+      },
+    },
+    methods: {
+      handleChildren(children = [], parent) {
+        if (children === null) children = []
+        const showChildren = children.filter((item) => {
+          if (item.hidden) {
+            return false
+          } else {
+            this.routeChildren = item
+            return true
+          }
+        })
+        if (showChildren.length === 1) {
+          return true
+        }
+
+        if (showChildren.length === 0) {
+          this.routeChildren = {
+            ...parent,
+            path: '',
+            notShowChildren: true,
+          }
+          return true
+        }
+        return false
+      },
+      handlePath(routePath) {
+        if (isExternal(routePath)) {
+          return routePath
+        }
+        if (isExternal(this.fullPath)) {
+          return this.fullPath
+        }
+        return path.resolve(this.fullPath, routePath)
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  .vab-nav-icon {
+    margin-right: 4px;
+  }
+
+  ::v-deep {
+    .el-tag {
+      float: right;
+      height: 16px;
+      padding-right: 4px;
+      padding-left: 4px;
+      margin-top: calc((#{$base-menu-item-height} - 16px) / 2);
+      line-height: 16px;
+      border: 0;
+    }
+  }
+</style>

+ 60 - 0
layouts/VabSideBar/components/VabSubmenu.vue

@@ -0,0 +1,60 @@
+<template>
+  <el-submenu
+    ref="subMenu"
+    :index="handlePath(item.path)"
+    :popper-append-to-body="false"
+  >
+    <template slot="title">
+      <vab-icon
+        v-if="item.meta && item.meta.icon"
+        :icon="['fas', item.meta.icon]"
+        class="vab-fas-icon"
+      />
+      <vab-remix-icon
+        v-if="item.meta && item.meta.remixIcon"
+        :icon-class="item.meta.remixIcon"
+        class="vab-remix-icon"
+      />
+      <span>{{ item.meta.title }}</span>
+    </template>
+    <slot />
+  </el-submenu>
+</template>
+
+<script>
+  import { isExternal } from '@/utils/validate'
+  import path from 'path'
+
+  export default {
+    name: 'VabSubmenu',
+    props: {
+      routeChildren: {
+        type: Object,
+        default() {
+          return null
+        },
+      },
+      item: {
+        type: Object,
+        default() {
+          return null
+        },
+      },
+      fullPath: {
+        type: String,
+        default: '',
+      },
+    },
+    methods: {
+      handlePath(routePath) {
+        if (isExternal(routePath)) {
+          return routePath
+        }
+        if (isExternal(this.fullPath)) {
+          return this.fullPath
+        }
+        return path.resolve(this.fullPath, routePath)
+      },
+    },
+  }
+</script>

+ 141 - 0
layouts/VabSideBar/index.vue

@@ -0,0 +1,141 @@
+<template>
+  <el-scrollbar class="side-bar-container" :class="{ 'is-collapse': collapse }">
+    <vab-logo />
+    <el-menu
+      :background-color="variables['menu-background']"
+      :text-color="variables['menu-color']"
+      :active-text-color="variables['menu-color-active']"
+      :default-active="activeMenu"
+      :collapse="collapse"
+      :collapse-transition="false"
+      :default-openeds="defaultOpens"
+      :unique-opened="uniqueOpened"
+      mode="vertical"
+    >
+      <template v-for="route in routes">
+        <vab-side-bar-item
+          :key="route.path"
+          :full-path="route.path"
+          :item="route"
+        />
+      </template>
+    </el-menu>
+  </el-scrollbar>
+</template>
+<script>
+  import variables from '@/styles/variables.scss'
+  import { mapGetters } from 'vuex'
+  import { defaultOopeneds, uniqueOpened } from '@/config'
+
+  export default {
+    name: 'VabSideBar',
+    data() {
+      return {
+        uniqueOpened,
+      }
+    },
+    computed: {
+      ...mapGetters({
+        collapse: 'settings/collapse',
+        routes: 'routes/routes',
+      }),
+      defaultOpens() {
+        if (this.collapse) {
+        }
+        return defaultOopeneds
+      },
+      activeMenu() {
+        const route = this.$route
+        const { meta, path } = route
+        if (meta.activeMenu) {
+          return meta.activeMenu
+        }
+        return path
+      },
+      variables() {
+        return variables
+      },
+    },
+  }
+</script>
+<style lang="scss" scoped>
+  @mixin active {
+    &:hover {
+      color: $base-color-white;
+      background-color: $base-menu-background-active !important;
+    }
+
+    &.is-active {
+      color: $base-color-white;
+      background-color: $base-menu-background-active !important;
+    }
+  }
+
+  .side-bar-container {
+    position: fixed;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    z-index: $base-z-index;
+    width: $base-left-menu-width;
+    height: 100vh;
+    overflow: hidden;
+    background: $base-menu-background;
+    box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35);
+    transition: width $base-transition-time;
+
+    &.is-collapse {
+      width: $base-left-menu-width-min;
+      border-right: 0;
+
+      ::v-deep {
+        .el-menu {
+          transition: width $base-transition-time;
+        }
+
+        .el-menu--collapse {
+          border-right: 0;
+
+          .el-submenu__icon-arrow {
+            right: 10px;
+            margin-top: -3px;
+          }
+        }
+      }
+    }
+
+    ::v-deep {
+      .el-scrollbar__wrap {
+        overflow-x: hidden;
+      }
+
+      .el-menu {
+        border: 0;
+
+        .vab-fas-icon {
+          padding-right: 3px;
+          font-size: $base-font-size-default;
+        }
+
+        .vab-remix-icon {
+          padding-right: 3px;
+          font-size: $base-font-size-default + 2;
+        }
+      }
+
+      .el-menu-item,
+      .el-submenu__title {
+        height: $base-menu-item-height;
+        overflow: hidden;
+        line-height: $base-menu-item-height;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        vertical-align: middle;
+      }
+
+      .el-menu-item {
+        @include active;
+      }
+    }
+  }
+</style>

+ 293 - 0
layouts/VabTabsBar/index.vue

@@ -0,0 +1,293 @@
+<template>
+  <div id="tabs-bar-container" class="tabs-bar-container">
+    <el-tabs
+      v-model="tabActive"
+      type="card"
+      class="tabs-content"
+      @tab-click="handleTabClick"
+      @tab-remove="handleTabRemove"
+    >
+      <el-tab-pane
+        v-for="item in visitedRoutes"
+        :key="item.path"
+        :label="item.meta.title"
+        :name="item.path"
+        :closable="!isAffix(item)"
+      ></el-tab-pane>
+    </el-tabs>
+
+    <el-dropdown @command="handleCommand">
+      <span style="cursor: pointer">
+        更多操作
+        <i class="el-icon-arrow-down el-icon--right"></i>
+      </span>
+      <el-dropdown-menu slot="dropdown" class="tabs-more">
+        <el-dropdown-item command="closeOtherstabs">
+          <vab-icon :icon="['fas', 'times-circle']" />
+          关闭其他
+        </el-dropdown-item>
+        <el-dropdown-item command="closeLefttabs">
+          <vab-icon :icon="['fas', 'arrow-alt-circle-left']"></vab-icon>
+          关闭左侧
+        </el-dropdown-item>
+        <el-dropdown-item command="closeRighttabs">
+          <vab-icon :icon="['fas', 'arrow-alt-circle-right']"></vab-icon>
+          关闭右侧
+        </el-dropdown-item>
+        <el-dropdown-item command="closeAlltabs">
+          <vab-icon :icon="['fas', 'ban']"></vab-icon>
+          关闭全部
+        </el-dropdown-item>
+      </el-dropdown-menu>
+    </el-dropdown>
+  </div>
+</template>
+
+<script>
+  import path from 'path'
+  import { mapGetters } from 'vuex'
+
+  export default {
+    name: 'VabTabsBar',
+    data() {
+      return {
+        affixtabs: [],
+        tabActive: '',
+      }
+    },
+
+    computed: {
+      ...mapGetters({
+        visitedRoutes: 'tabsBar/visitedRoutes',
+        routes: 'routes/routes',
+      }),
+    },
+    watch: {
+      $route: {
+        handler(route) {
+          this.inittabs()
+          this.addtabs()
+          let tabActive = ''
+          this.visitedRoutes.forEach((item, index) => {
+            if (item.path === this.$route.path) {
+              tabActive = item.path
+            }
+          })
+          this.tabActive = tabActive
+        },
+        immediate: true,
+      },
+    },
+    mounted() {
+      //console.log(this.visitedRoutes);
+    },
+    methods: {
+      async handleTabRemove(tabActive) {
+        let view
+        this.visitedRoutes.forEach((item, index) => {
+          if (tabActive === item.path) {
+            view = item
+          }
+        })
+        const { visitedRoutes } = await this.$store.dispatch(
+          'tabsBar/delRoute',
+          view
+        )
+        if (this.isActive(view)) {
+          this.toLastTag(visitedRoutes, view)
+        }
+      },
+      handleTabClick(tab) {
+        const route = this.visitedRoutes.filter((item, index) => {
+          if (tab.index == index) return item
+        })[0]
+        if (this.$route.path !== route.path) {
+          this.$router.push({
+            path: route.path,
+            query: route.query,
+            fullPath: route.fullPath,
+          })
+        } else {
+          return false
+        }
+      },
+      isActive(route) {
+        return route.path === this.$route.path
+      },
+      isAffix(tag) {
+        return tag.meta && tag.meta.affix
+      },
+      filterAffixtabs(routes, basePath = '/') {
+        let tabs = []
+        routes.forEach((route) => {
+          if (route.meta && route.meta.affix) {
+            const tagPath = path.resolve(basePath, route.path)
+            tabs.push({
+              fullPath: tagPath,
+              path: tagPath,
+              name: route.name,
+              meta: { ...route.meta },
+            })
+          }
+          if (route.children) {
+            const temptabs = this.filterAffixtabs(route.children, route.path)
+            if (temptabs.length >= 1) {
+              tabs = [...tabs, ...temptabs]
+            }
+          }
+        })
+        return tabs
+      },
+      inittabs() {
+        const affixtabs = (this.affixtabs = this.filterAffixtabs(this.routes))
+        for (const tag of affixtabs) {
+          if (tag.name) {
+            this.$store.dispatch('tabsBar/addVisitedRoute', tag)
+          }
+        }
+      },
+      addtabs() {
+        const { name } = this.$route
+        if (name) {
+          this.$store.dispatch('tabsBar/addVisitedRoute', this.$route)
+        }
+        return false
+      },
+      handleCommand(command) {
+        switch (command) {
+          case 'refreshRoute':
+            this.refreshRoute()
+            break
+          case 'closeOtherstabs':
+            this.closeOtherstabs()
+            break
+          case 'closeLefttabs':
+            this.closeLefttabs()
+            break
+          case 'closeRighttabs':
+            this.closeRighttabs()
+            break
+          case 'closeAlltabs':
+            this.closeAlltabs()
+            break
+        }
+      },
+      async refreshRoute() {
+        this.$baseEventBus.$emit('reloadrouter-view')
+      },
+      async closeSelectedTag(view) {
+        const { visitedRoutes } = await this.$store.dispatch(
+          'tabsBar/delRoute',
+          view
+        )
+        if (this.isActive(view)) {
+          this.toLastTag(visitedRoutes, view)
+        }
+      },
+      async closeOtherstabs() {
+        const view = await this.toThisTag()
+        await this.$store.dispatch('tabsBar/delOthersRoutes', view)
+      },
+      async closeLefttabs() {
+        const view = await this.toThisTag()
+        await this.$store.dispatch('tabsBar/delLeftRoutes', view)
+      },
+      async closeRighttabs() {
+        const view = await this.toThisTag()
+        await this.$store.dispatch('tabsBar/delRightRoutes', view)
+      },
+      async closeAlltabs() {
+        const view = await this.toThisTag()
+        const { visitedRoutes } = await this.$store.dispatch(
+          'tabsBar/delAllRoutes'
+        )
+        if (this.affixtabs.some((tag) => tag.path === view.path)) {
+          return
+        }
+        this.toLastTag(visitedRoutes, view)
+      },
+      toLastTag(visitedRoutes, view) {
+        const latestView = visitedRoutes.slice(-1)[0]
+        if (latestView) {
+          this.$router.push(latestView)
+        } else {
+          this.$router.push('/')
+        }
+      },
+      async toThisTag() {
+        const view = this.visitedRoutes.filter((item, index) => {
+          if (item.path === this.$route.fullPath) {
+            return item
+          }
+        })[0]
+        if (this.$route.path !== view.path) this.$router.push(view)
+        return view
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  .tabs-bar-container {
+    position: relative;
+    box-sizing: border-box;
+    display: flex;
+    align-content: center;
+    align-items: center;
+    justify-content: space-between;
+    height: $base-tags-bar-height;
+    padding-right: $base-padding;
+    padding-left: $base-padding;
+    user-select: none;
+    background: $base-color-white;
+    border-top: 1px solid #f6f6f6;
+
+    ::v-deep {
+      .fold-unfold {
+        margin-right: $base-padding;
+      }
+    }
+
+    .tabs-content {
+      width: calc(100% - 90px);
+      height: $base-tag-item-height;
+
+      ::v-deep {
+        .el-tabs__nav-next,
+        .el-tabs__nav-prev {
+          height: $base-tag-item-height;
+          line-height: $base-tag-item-height;
+        }
+
+        .el-tabs__header {
+          border-bottom: 0;
+
+          .el-tabs__nav {
+            border: 0;
+          }
+
+          .el-tabs__item {
+            box-sizing: border-box;
+            height: $base-tag-item-height;
+            margin-right: 5px;
+            line-height: $base-tag-item-height;
+            border: 1px solid $base-border-color;
+            border-radius: $base-border-radius;
+            transition: padding 0.3s cubic-bezier(0.645, 0.045, 0.355, 1) !important;
+
+            &.is-active {
+              border: 1px solid $base-color-blue;
+            }
+          }
+        }
+      }
+    }
+
+    .more {
+      display: flex;
+      align-content: center;
+      align-items: center;
+      cursor: pointer;
+    }
+  }
+</style>

+ 224 - 0
layouts/VabTopBar/index.vue

@@ -0,0 +1,224 @@
+<template>
+  <div class="top-bar-container">
+    <div class="vab-main">
+      <el-row>
+        <el-col :xl="7" :lg="7" :md="7" :sm="7" :xs="7">
+          <vab-logo />
+        </el-col>
+        <el-col :xl="12" :lg="12" :md="12" :sm="12" :xs="12">
+          <el-menu
+            :background-color="variables['menu-background']"
+            :text-color="variables['menu-color']"
+            :active-text-color="variables['menu-color-active']"
+            :default-active="activeMenu"
+            mode="horizontal"
+            menu-trigger="hover"
+          >
+            <template v-for="route in routes">
+              <vab-side-bar-item
+                v-if="!route.hidden"
+                :key="route.path"
+                :full-path="route.path"
+                :item="route"
+              />
+            </template>
+          </el-menu>
+        </el-col>
+        <el-col :xl="5" :lg="5" :md="5" :sm="5" :xs="5">
+          <div class="right-panel">
+            <vab-error-log />
+            <vab-full-screen-bar @refresh="refreshRoute" />
+            <vab-theme-bar class="hidden-md-and-down" />
+            <vab-icon
+              title="重载路由"
+              :pulse="pulse"
+              :icon="['fas', 'redo']"
+              @click="refreshRoute"
+            />
+            <vab-avatar />
+          </div>
+        </el-col>
+      </el-row>
+    </div>
+  </div>
+</template>
+
+<script>
+  import variables from '@/styles/variables.scss'
+  import { mapGetters } from 'vuex'
+
+  export default {
+    name: 'VabTopBar',
+    data() {
+      return {
+        pulse: false,
+        menuTrigger: 'hover',
+      }
+    },
+    computed: {
+      ...mapGetters({
+        routes: 'routes/routes',
+        visitedRoutes: 'tabsBar/visitedRoutes',
+      }),
+      activeMenu() {
+        const route = this.$route
+        const { meta, path } = route
+        if (meta.activeMenu) {
+          return meta.activeMenu
+        }
+        return path
+      },
+      variables() {
+        return variables
+      },
+    },
+    methods: {
+      async refreshRoute() {
+        this.$baseEventBus.$emit('reload-router-view')
+        this.pulse = true
+        setTimeout(() => {
+          this.pulse = false
+        }, 1000)
+      },
+    },
+  }
+</script>
+<style lang="scss" scoped>
+  .top-bar-container {
+    display: flex;
+    align-items: center;
+    justify-items: flex-end;
+    height: $base-top-bar-height;
+    background: $base-menu-background;
+
+    .vab-main {
+      background: $base-menu-background;
+
+      ::v-deep {
+        .el-menu {
+          &.el-menu--horizontal {
+            display: flex;
+            align-items: center;
+            justify-content: flex-end;
+            height: $base-top-bar-height;
+            border-bottom: 0 solid transparent !important;
+
+            .el-menu-item,
+            .el-submenu__title {
+              padding: 0 15px;
+            }
+
+            @media only screen and (max-width: 767px) {
+              .el-menu-item,
+              .el-submenu__title {
+                padding: 0 8px;
+              }
+
+              li:nth-child(4),
+              li:nth-child(5) {
+                display: none !important;
+              }
+            }
+
+            > .el-menu-item {
+              height: $base-top-bar-height;
+              line-height: $base-top-bar-height;
+            }
+
+            > .el-submenu {
+              .el-submenu__title {
+                height: $base-top-bar-height;
+                line-height: $base-top-bar-height;
+              }
+            }
+          }
+
+          svg {
+            width: 1rem;
+            margin-right: 3px;
+          }
+
+          &--horizontal {
+            .el-menu {
+              .el-menu-item,
+              .el-submenu__title {
+                height: $base-menu-item-height;
+                line-height: $base-menu-item-height;
+              }
+            }
+
+            .el-submenu,
+            .el-menu-item {
+              &.is-active {
+                background-color: $base-color-blue !important;
+                border-bottom: 0 solid transparent !important;
+
+                .el-submenu__title {
+                  border-bottom: 0 solid transparent !important;
+                }
+              }
+            }
+
+            > .el-menu-item {
+              .el-tag {
+                margin-top: calc(#{$base-top-bar-height} / 2 - 7.5px);
+                margin-left: 5px;
+              }
+
+              @media only screen and (max-width: 1199px) {
+                .el-tag {
+                  display: none;
+                }
+              }
+
+              &.is-active {
+                background-color: transparent !important;
+                border-bottom: 3px solid $base-color-blue !important;
+              }
+            }
+          }
+        }
+      }
+    }
+
+    .right-panel {
+      display: flex;
+      align-items: center;
+      justify-content: flex-end;
+      height: $base-top-bar-height;
+
+      ::v-deep {
+        .user-name {
+          color: rgba($base-color-white, 0.9);
+        }
+
+        .user-name + i {
+          color: rgba($base-color-white, 0.9);
+        }
+
+        svg {
+          width: 1em;
+          height: 1em;
+          margin-right: 15px;
+          font-size: $base-font-size-big;
+          color: rgba($base-color-white, 0.9);
+          cursor: pointer;
+          fill: rgba($base-color-white, 0.9);
+        }
+
+        button {
+          svg {
+            margin-right: 0;
+            color: rgba($base-color-white, 0.9);
+            cursor: pointer;
+            fill: rgba($base-color-white, 0.9);
+          }
+        }
+
+        .el-badge {
+          margin-right: 15px;
+        }
+      }
+    }
+  }
+</style>

+ 31 - 0
layouts/index.js

@@ -0,0 +1,31 @@
+/* eslint-disable */
+const chalk = require('chalk')
+module.exports = {
+  webpackBarName: 'vue-admin-better',
+  webpackBanner:
+    ' build: vue-admin-better \n vue-admin-beautiful.com \n https://gitee.com/chu1204505056/vue-admin-better \n time: ',
+  donationConsole() {
+    const chalk = require('chalk')
+    console.log(
+      chalk.green(
+        `> 欢迎使用XX系统,github开源地址:https://github.com/hiparker/opsli-boot`
+      )
+    )
+    console.log(
+      chalk.green(
+        `> 欢迎使用XX系统,码云开源地址:https://gitee.com/hiparker/opsli-boot`
+      )
+    )
+
+    console.log(chalk.green(`> 本程序 前端使用 vue-admin-better 开源版本`))
+
+    console.log(
+      chalk.green(
+        `> 使用中出现任何问题可加QQ群反馈,获取基础版、文档,请我们喝杯咖啡(如若情况不允许,请勿勉强)`
+      )
+    )
+
+    console.log(chalk.green(`> 如果您不希望显示以上信息,可在config中配置关闭`))
+    console.log('\n')
+  },
+}

+ 5 - 0
layouts/package.json

@@ -0,0 +1,5 @@
+{
+  "name": "layouts",
+  "version": "1.0.0",
+  "main": "index.js"
+}

+ 17 - 0
layouts/prettier.config.js

@@ -0,0 +1,17 @@
+/* eslint-disable */
+module.exports = {
+  printWidth: 80,
+  tabWidth: 2,
+  useTabs: false,
+  semi: false,
+  singleQuote: true,
+  quoteProps: 'as-needed',
+  jsxSingleQuote: false,
+  trailingComma: 'es5',
+  bracketSpacing: true,
+  jsxBracketSameLine: false,
+  arrowParens: 'always',
+  htmlWhitespaceSensitivity: 'ignore',
+  vueIndentScriptAndStyle: true,
+  endOfLine: 'lf',
+}

+ 242 - 0
layouts/入口界面.html

@@ -0,0 +1,242 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>入口界面</title>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+  <link href="resources/css/axure_rp_page.css" type="text/css" rel="stylesheet" />
+  <link href="data/styles.css" type="text/css" rel="stylesheet" />
+  <link href="files/入口界面/styles.css" type="text/css" rel="stylesheet" />
+  <link href="https://fonts.googleapis.com" rel="preconnect" />
+  <link href="https://fonts.gstatic.com" rel="preconnect" />
+  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet" />
+
+  <!-- 引入 Vue.js -->
+  <script src="resources/scripts/vue.js"></script>
+  <!-- 本地引入Vue Router -->
+  <script src="resources/scripts/vue-router.js"></script>
+  <script src="resources/scripts/jquery-3.7.1.min.js"></script>
+  <script src="resources/scripts/axure/axQuery.js"></script>
+  <script src="resources/scripts/axure/globals.js"></script>
+  <script src="resources/scripts/axutils.js"></script>
+  <script src="resources/scripts/axure/annotation.js"></script>
+  <script src="resources/scripts/axure/axQuery.std.js"></script>
+  <script src="resources/scripts/axure/doc.js"></script>
+  <script src="resources/scripts/messagecenter.js"></script>
+  <script src="resources/scripts/axure/events.js"></script>
+  <script src="resources/scripts/axure/recording.js"></script>
+  <script src="resources/scripts/axure/action.js"></script>
+  <script src="resources/scripts/axure/expr.js"></script>
+  <script src="resources/scripts/axure/geometry.js"></script>
+  <script src="resources/scripts/axure/flyout.js"></script>
+  <script src="resources/scripts/axure/model.js"></script>
+  <script src="resources/scripts/axure/repeater.js"></script>
+  <script src="resources/scripts/axure/sto.js"></script>
+  <script src="resources/scripts/axure/utils.temp.js"></script>
+  <script src="resources/scripts/axure/variables.js"></script>
+  <script src="resources/scripts/axure/drag.js"></script>
+  <script src="resources/scripts/axure/move.js"></script>
+  <script src="resources/scripts/axure/visibility.js"></script>
+  <script src="resources/scripts/axure/style.js"></script>
+  <script src="resources/scripts/axure/adaptive.js"></script>
+  <script src="resources/scripts/axure/tree.js"></script>
+  <script src="resources/scripts/axure/init.temp.js"></script>
+  <script src="resources/scripts/axure/legacy.js"></script>
+  <script src="resources/scripts/axure/viewer.js"></script>
+  <script src="resources/scripts/axure/math.js"></script>
+  <script src="resources/scripts/axure/jquery.nicescroll.min.js"></script>
+  <script src="data/document.js"></script>
+  <script src="files/入口界面/data.js"></script>
+  <script type="text/javascript">
+    $axure.utils.getTransparentGifPath = function () { return 'resources/images/transparent.gif'; };
+    $axure.utils.getOtherPath = function () { return 'resources/Other.html'; };
+    $axure.utils.getReloadPath = function () { return 'resources/reload.html'; };
+  </script>
+</head>
+
+<body>
+<!-- 绑定 Vue 实例的元素 -->
+<div id="app" style="width: 100%;height: 100%">
+  <div id="base" class="" style="width: 100%;height: 100%">
+
+    <!-- 背景 (Dynamic panel) -->
+    <div id="u50" class="ax_default" data-label="背景">
+      <div id="u50_state0" class="panel_state" data-label="背景" style="">
+        <div id="u50_state0_content" class="panel_state_content">
+        </div>
+      </div>
+    </div>
+
+    <!-- 标题 (Group) -->
+    <div id="u51" class="ax_default" data-label="标题" data-left="0" data-top="0" data-width="1920" data-height="132" layer-opacity="1">
+
+      <!-- Unnamed (Image) -->
+      <div id="u52" class="ax_default _默认样式 transition notrs">
+        <img id="u52_img" class="img " src="images/入口界面/u52.png" />
+        <div id="u52_text" class="text " style="display:none; visibility: hidden">
+          <p></p>
+        </div>
+      </div>
+
+      <!-- Unnamed (Rectangle) -->
+      <div id="u53" class="ax_default _默认样式 transition notrs">
+        <div id="u53_div" class=""></div>
+        <div id="u53_text" class="text ">
+          <p><span>XXBQ辅助指挥决策系统</span></p>
+        </div>
+      </div>
+    </div>
+
+    <!-- 指挥决策子系统 (Group) -->
+    <div id="u54" class="ax_default" data-left="838" data-top="249" data-width="314" data-height="338" layer-opacity="1" style="position: relative; z-index: 1;">
+
+
+    </div>
+    <!-- 筹划推演子系统 (Group) -->
+    <div id="u71" class="ax_default" data-left="283" data-top="249" data-width="314" data-height="338" layer-opacity="1" style="position: relative; z-index: 1;">
+
+      <!-- Unnamed (Image) -->
+      <div id="u72" class="ax_default _默认样式 transition notrs" @click="showPlanSubmenu">
+        <img id="u72_img" class="img " src="images/入口界面/u55.png" />
+        <img class="logo-img" src="images/入口界面/u57.svg" />
+        <p><span>筹划推演子系统</span></p>
+      </div>
+
+      <!-- Unnamed (Image) -->
+      <div id="u72" class="ax_default _默认样式 transition notrs" @click="showCommandSubmenu">
+        <img id="u72_img" class="img " src="images/入口界面/u55.png" />
+        <img class="logo-img" src="images/入口界面/u57.svg" />
+        <p><span>指挥决策子系统</span></p>
+      </div>
+
+      <!-- Unnamed (Image) -->
+      <div id="u72" class="ax_default _默认样式 transition notrs" @click="showReviewSubmenu">
+        <img id="u72_img" class="img " src="images/入口界面/u55.png" />
+        <img class="logo-img" src="images/入口界面/u57.svg" />
+        <p><span>复盘分析子系统</span></p>
+      </div>
+    </div>
+
+    <!-- 子菜单 (合并两个菜单为一个) -->
+    <div id="u58" class="ax_default" :style="{ display: submenuVisible ? '' : 'none' }" data-left="668" data-top="741" data-width="614" data-height="130" layer-opacity="1">
+
+      <!-- 第一个子模块 -->
+      <div v-for="item in submenuItems" @click="handleSubmenuClick(item)" id="u59" class="ax_default" layer-opacity="1">
+
+        <div style="display: flex;flex-direction: column;align-items: center;justify-content: center">
+          <!-- 图标 -->
+          <div id="u60" class="ax_default _默认样式 transition notrs">
+            <div id="u60_div" class=""></div>
+            <div id="u60_text" class="text ">
+<!--              <p><span>{{ item.icon }}</span></p>-->
+              <img style="width: 50px;margin-top: 5px;" src="./images/入口界面/设置.svg" alt="">
+            </div>
+          </div>
+
+          <!-- 文字 -->
+          <div id="u61" class="ax_default _默认样式 transition notrs">
+            <div id="u61_div" class=""></div>
+            <div id="u61_text" class="text ">
+              <p><span>{{ item.text }}</span></p>
+            </div>
+          </div>
+        </div>
+
+      </div>
+    </div>
+
+
+
+<!--    &lt;!&ndash; Unnamed (Hot spot) &ndash;&gt;-->
+<!--    <div id="u79" class="ax_default">-->
+<!--    </div>-->
+
+<!--    &lt;!&ndash; Unnamed (Hot spot) &ndash;&gt;-->
+<!--    <div id="u80" class="ax_default" @click="showPlanSubmenu">-->
+<!--    </div>-->
+
+<!--    &lt;!&ndash; Unnamed (Hot spot) &ndash;&gt;-->
+<!--    <div id="u81" class="ax_default">-->
+<!--    </div>-->
+
+<!--    &lt;!&ndash; Unnamed (Hot spot) &ndash;&gt;-->
+<!--    <div id="u82" class="ax_default">-->
+<!--    </div>-->
+
+<!--    &lt;!&ndash; Unnamed (Hot spot) &ndash;&gt;-->
+<!--    <div id="u83" class="ax_default">-->
+<!--    </div>-->
+
+<!--    &lt;!&ndash; Unnamed (Hot spot) &ndash;&gt;-->
+<!--    <div id="u84" class="ax_default">-->
+<!--    </div>-->
+
+<!--    &lt;!&ndash; Unnamed (Hot spot) &ndash;&gt;-->
+<!--    <div id="u85" class="ax_default">-->
+<!--    </div>-->
+  </div>
+</div>
+<script>
+  // 初始化Vue实例
+  new Vue({
+    el: '#app',
+    data: {
+      submenuVisible: false,
+      currentSubmenu: '',
+      submenuItems: [
+
+      ],
+    },
+    methods: {
+      showPlanSubmenu() {
+        this.currentSubmenu = 'plan';
+        this.submenuVisible = true;
+        this.submenuItems = [
+          { icon: '', text: '方案生成',path: '/plan' },
+          { icon: '', text: '仿真推演' ,path: '/plan'},
+          { icon: '', text: '模型及数据管理',path: '/plan' },
+          { icon: '', text: 'AI应用' ,path: '/plan'}
+        ];
+      },
+      showCommandSubmenu() {
+        this.currentSubmenu = 'command';
+        this.submenuVisible = true;
+        this.submenuItems = [
+          { icon: '', text: '辅助决策',path: '/command' },
+          { icon: '', text: '态势显示',path: '/command' },
+          { icon: '', text: '数据实时处理及分发',path: '/command' },
+        ];
+      },
+      showReviewSubmenu(){
+        this.currentSubmenu = 'review';
+        this.submenuVisible = true;
+        this.submenuItems = [];
+      },
+
+      // 子菜单点击处理
+      handleSubmenuClick(item) {
+        switch (item.path){
+          case '/plan':
+            window.location.href = './views/src/index.html';
+            break;
+          case '/command':
+            window.location.href = './views/src/指挥决策子系统.html';
+            break;
+          case '/review':
+
+            break;
+        }
+        /*// 跳转到对应的子模块路由
+        this.$router.push(path);
+        // 隐藏子菜单
+        this.submenuVisible = false;*/
+
+      }
+    }
+  });
+</script>
+<script src="resources/scripts/axure/ios.js"></script>
+</body>
+
+</html>

+ 591 - 0
layouts/登录界面.html

@@ -0,0 +1,591 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>登录界面</title>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+    <link href="resources/css/axure_rp_page.css" type="text/css" rel="stylesheet"/>
+    <link href="data/styles.css" type="text/css" rel="stylesheet"/>
+    <link href="files/登录界面/styles.css" type="text/css" rel="stylesheet"/>
+    <link href="https://fonts.googleapis.com" rel="preconnect"/>
+    <link href="https://fonts.gstatic.com" rel="preconnect"/>
+    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet"/>
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
+    <script src="resources/scripts/jquery-3.7.1.min.js"></script>
+    <script src="resources/scripts/axure/axQuery.js"></script>
+    <script src="resources/scripts/axure/globals.js"></script>
+    <script src="resources/scripts/axutils.js"></script>
+    <script src="resources/scripts/axure/annotation.js"></script>
+    <script src="resources/scripts/axure/axQuery.std.js"></script>
+    <script src="resources/scripts/axure/doc.js"></script>
+    <script src="resources/scripts/messagecenter.js"></script>
+    <script src="resources/scripts/axure/events.js"></script>
+    <script src="resources/scripts/axure/recording.js"></script>
+    <script src="resources/scripts/axure/action.js"></script>
+    <script src="resources/scripts/axure/expr.js"></script>
+    <script src="resources/scripts/axure/geometry.js"></script>
+    <script src="resources/scripts/axure/flyout.js"></script>
+    <script src="resources/scripts/axure/model.js"></script>
+    <script src="resources/scripts/axure/repeater.js"></script>
+    <script src="resources/scripts/axure/sto.js"></script>
+    <script src="resources/scripts/axure/utils.temp.js"></script>
+    <script src="resources/scripts/axure/variables.js"></script>
+    <script src="resources/scripts/axure/drag.js"></script>
+    <script src="resources/scripts/axure/move.js"></script>
+    <script src="resources/scripts/axure/visibility.js"></script>
+    <script src="resources/scripts/axure/style.js"></script>
+    <script src="resources/scripts/axure/adaptive.js"></script>
+    <script src="resources/scripts/axure/tree.js"></script>
+    <script src="resources/scripts/axure/init.temp.js"></script>
+    <script src="resources/scripts/axure/legacy.js"></script>
+    <script src="resources/scripts/axure/viewer.js"></script>
+    <script src="resources/scripts/axure/math.js"></script>
+    <script src="resources/scripts/axure/jquery.nicescroll.min.js"></script>
+    <script src="data/document.js"></script>
+    <script src="files/登录界面/data.js"></script>
+    <script type="text/javascript">
+      $axure.utils.getTransparentGifPath = function() { return 'resources/images/transparent.gif'; };
+      $axure.utils.getOtherPath = function() { return 'resources/Other.html'; };
+      $axure.utils.getReloadPath = function() { return 'resources/reload.html'; };
+    </script>
+  </head>
+  <body>
+    <div id="base" class="">
+
+      <!-- Unnamed (登录界面02(验证码+账号验证)) -->
+      <div id="u0" class="nopointer  ax_default">
+
+        <!-- 背景 (Dynamic panel) -->
+        <div id="u1" class="ax_default" data-label="背景">
+          <div id="u1_state0" class="panel_state" data-label="背景" style="">
+            <div id="u1_state0_content" class="panel_state_content">
+            </div>
+          </div>
+        </div>
+
+        <!-- 登录面板 (Dynamic panel) -->
+        <div id="u2" class="ax_default" data-label="登录面板">
+          <div id="u2_state0" class="panel_state" data-label="登录面板" style="">
+            <div id="u2_state0_content" class="panel_state_content">
+
+              <!-- Unnamed (SVG) -->
+              <div id="u3" class="ax_default _默认样式 transition notrs">
+                <img id="u3_img" class="img " src="images/登录界面/u3.svg"/>
+                <div id="u3_text" class="text " style="display:none; visibility: hidden">
+                  <p></p>
+                </div>
+              </div>
+
+              <!-- 标题 (Group) -->
+              <div id="u4" class="ax_default" data-label="标题" data-left="0" data-top="32" data-width="457" data-height="70" layer-opacity="1">
+
+                <!-- Unnamed (SVG) -->
+                <div id="u5" class="ax_default _默认样式 transition notrs">
+                  <img id="u5_img" class="img " src="images/登录界面/u5.svg"/>
+                  <div id="u5_text" class="text " style="display:none; visibility: hidden">
+                    <p></p>
+                  </div>
+                </div>
+
+                <!-- Unnamed (Rectangle) -->
+                <div id="u6" class="ax_default _默认样式1 transition notrs">
+                  <div id="u6_div" class=""></div>
+                  <div id="u6_text" class="text ">
+                    <p><span>XXBQ辅助指挥决策系统</span></p><p><span>&nbsp;</span></p>
+                  </div>
+                </div>
+              </div>
+
+              <!-- 框体 (Group) -->
+              <div id="u7" class="ax_default" data-label="框体" data-left="0" data-top="115" data-width="482" data-height="480" layer-opacity="1">
+
+                <!-- Unnamed (Rectangle) -->
+                <div id="u8" class="ax_default _默认样式 transition notrs">
+                  <svg data="images/登录界面/u8.svg" id="u8_img" class="img generatedImage">
+
+  <defs>
+    <pattern id="u8_img_bgp" patternUnits="userSpaceOnUse" alignment="0 0" imageRepeat="None" />
+    <linearGradient gradientUnits="userSpaceOnUse" x1="241" y1="0" x2="241" y2="462" id="u8_img_lg19">
+      <stop id="Stop20" stop-color="#03b4f5" stop-opacity="0.2" offset="0" />
+      <stop id="Stop21" stop-color="#03b4f5" stop-opacity="0.8980392156862745" offset="0.28" />
+      <stop id="Stop22" stop-color="#03b4f5" stop-opacity="0.8980392156862745" offset="0.74" />
+      <stop id="Stop23" stop-color="#03b4f5" stop-opacity="0.2" offset="1" />
+    </linearGradient>
+  </defs>
+  <g transform="matrix(1 0 0 1 0 -122 )">
+    <path d="M 0 462  L 0 0  L 482 0  L 482 462  L 0 462  Z " fill-rule="nonzero" fill="rgba(3, 180, 245, 0.24705882352941178)" stroke="none" transform="matrix(1 0 0 1 0 122 )" class="fill" />
+    <path d="M 481.5 0  L 481.5 462  M 0.5 462  L 0.5 0  " stroke-width="1" stroke-dasharray="0" stroke="url(#u8_img_lg19)" fill="none" transform="matrix(1 0 0 1 0 122 )" class="stroke" />
+  </g>
+                  </svg>
+                  <div id="u8_text" class="text " style="display:none; visibility: hidden">
+                    <p></p>
+                  </div>
+                </div>
+
+                <!-- Unnamed (Shape) -->
+                <div id="u9" class="ax_default _形状 transition notrs">
+                  <svg data="images/登录界面/u9.svg" id="u9_img" class="img generatedImage">
+
+  <defs>
+    <pattern id="u9_img_bgp" patternUnits="userSpaceOnUse" alignment="0 0" imageRepeat="None" />
+    <mask fill="white" id="u9_img_cl24">
+      <path d="M 482 18.14541871921182  L 478.0110344827586 18.14541871921182  L 473.3572413793103 11  L 9.307586206896598 11  L 4.653793103448238 19.032118226601  L 0 19.032118226601  L 0 8.391724137930993  L 7.31310344827582 0.411428571428587  L 50.52689655172418 0.411428571428587  L 61.828965517241436 7.505024630541882  L 156.89931034482757 7.505024630541882  L 162.88275862068966 4  L 320.4468965517242 4  L 325.1006896551726 7.505024630541882  L 426.81931034482744 7.505024630541882  L 438.78620689655173 0.411428571428587  L 474.68689655172415 0.411428571428587  L 482 9.278423645320117  L 482 18.14541871921182  Z M 461.39034482758615 3.9582266009852276  L 458.73103448275856 3.9582266009852276  L 461.39034482758615 7.505024630541882  L 464.0496551724136 7.505024630541882  L 461.39034482758615 3.9582266009852276  Z M 466.7089655172413 3.9582266009852276  L 464.0496551724136 3.9582266009852276  L 466.7089655172413 7.505024630541882  L 469.368275862069 7.505024630541882  L 466.7089655172413 3.9582266009852276  Z M 474.68689655172415 7.505024630541882  L 472.0275862068965 3.9582266009852276  L 469.368275862069 3.9582266009852276  L 472.0275862068965 7.505024630541882  L 474.68689655172415 7.505024630541882  Z M 12.631724137931105 3.9582266009852276  L 9.972413793103401 3.9582266009852276  L 7.31310344827582 7.505024630541882  L 9.972413793103401 7.505024630541882  L 12.631724137931105 3.9582266009852276  Z M 17.950344827586267 3.9582266009852276  L 15.291034482758565 3.9582266009852276  L 12.631724137931105 7.505024630541882  L 15.291034482758565 7.505024630541882  L 17.950344827586267 3.9582266009852276  Z M 23.268965517241433 3.9582266009852276  L 20.609655172413728 3.9582266009852276  L 17.950344827586267 7.505024630541882  L 20.609655172413728 7.505024630541882  L 23.268965517241433 3.9582266009852276  Z " fill-rule="evenodd" />
+    </mask>
+  </defs>
+  <g transform="matrix(1 0 0 1 0 -115 )">
+    <path d="M 482 18.14541871921182  L 478.0110344827586 18.14541871921182  L 473.3572413793103 11  L 9.307586206896598 11  L 4.653793103448238 19.032118226601  L 0 19.032118226601  L 0 8.391724137930993  L 7.31310344827582 0.411428571428587  L 50.52689655172418 0.411428571428587  L 61.828965517241436 7.505024630541882  L 156.89931034482757 7.505024630541882  L 162.88275862068966 4  L 320.4468965517242 4  L 325.1006896551726 7.505024630541882  L 426.81931034482744 7.505024630541882  L 438.78620689655173 0.411428571428587  L 474.68689655172415 0.411428571428587  L 482 9.278423645320117  L 482 18.14541871921182  Z M 461.39034482758615 3.9582266009852276  L 458.73103448275856 3.9582266009852276  L 461.39034482758615 7.505024630541882  L 464.0496551724136 7.505024630541882  L 461.39034482758615 3.9582266009852276  Z M 466.7089655172413 3.9582266009852276  L 464.0496551724136 3.9582266009852276  L 466.7089655172413 7.505024630541882  L 469.368275862069 7.505024630541882  L 466.7089655172413 3.9582266009852276  Z M 474.68689655172415 7.505024630541882  L 472.0275862068965 3.9582266009852276  L 469.368275862069 3.9582266009852276  L 472.0275862068965 7.505024630541882  L 474.68689655172415 7.505024630541882  Z M 12.631724137931105 3.9582266009852276  L 9.972413793103401 3.9582266009852276  L 7.31310344827582 7.505024630541882  L 9.972413793103401 7.505024630541882  L 12.631724137931105 3.9582266009852276  Z M 17.950344827586267 3.9582266009852276  L 15.291034482758565 3.9582266009852276  L 12.631724137931105 7.505024630541882  L 15.291034482758565 7.505024630541882  L 17.950344827586267 3.9582266009852276  Z M 23.268965517241433 3.9582266009852276  L 20.609655172413728 3.9582266009852276  L 17.950344827586267 7.505024630541882  L 20.609655172413728 7.505024630541882  L 23.268965517241433 3.9582266009852276  Z " fill-rule="nonzero" fill="rgba(3, 180, 245, 1)" stroke="none" transform="matrix(1 0 0 1 0 115 )" class="fill" />
+    <path d="M 482 18.14541871921182  L 478.0110344827586 18.14541871921182  L 473.3572413793103 11  L 9.307586206896598 11  L 4.653793103448238 19.032118226601  L 0 19.032118226601  L 0 8.391724137930993  L 7.31310344827582 0.411428571428587  L 50.52689655172418 0.411428571428587  L 61.828965517241436 7.505024630541882  L 156.89931034482757 7.505024630541882  L 162.88275862068966 4  L 320.4468965517242 4  L 325.1006896551726 7.505024630541882  L 426.81931034482744 7.505024630541882  L 438.78620689655173 0.411428571428587  L 474.68689655172415 0.411428571428587  L 482 9.278423645320117  L 482 18.14541871921182  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 115 )" class="stroke" mask="url(#u9_img_cl24)" />
+    <path d="M 461.39034482758615 3.9582266009852276  L 458.73103448275856 3.9582266009852276  L 461.39034482758615 7.505024630541882  L 464.0496551724136 7.505024630541882  L 461.39034482758615 3.9582266009852276  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 115 )" class="stroke" mask="url(#u9_img_cl24)" />
+    <path d="M 466.7089655172413 3.9582266009852276  L 464.0496551724136 3.9582266009852276  L 466.7089655172413 7.505024630541882  L 469.368275862069 7.505024630541882  L 466.7089655172413 3.9582266009852276  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 115 )" class="stroke" mask="url(#u9_img_cl24)" />
+    <path d="M 474.68689655172415 7.505024630541882  L 472.0275862068965 3.9582266009852276  L 469.368275862069 3.9582266009852276  L 472.0275862068965 7.505024630541882  L 474.68689655172415 7.505024630541882  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 115 )" class="stroke" mask="url(#u9_img_cl24)" />
+    <path d="M 12.631724137931105 3.9582266009852276  L 9.972413793103401 3.9582266009852276  L 7.31310344827582 7.505024630541882  L 9.972413793103401 7.505024630541882  L 12.631724137931105 3.9582266009852276  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 115 )" class="stroke" mask="url(#u9_img_cl24)" />
+    <path d="M 17.950344827586267 3.9582266009852276  L 15.291034482758565 3.9582266009852276  L 12.631724137931105 7.505024630541882  L 15.291034482758565 7.505024630541882  L 17.950344827586267 3.9582266009852276  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 115 )" class="stroke" mask="url(#u9_img_cl24)" />
+    <path d="M 23.268965517241433 3.9582266009852276  L 20.609655172413728 3.9582266009852276  L 17.950344827586267 7.505024630541882  L 20.609655172413728 7.505024630541882  L 23.268965517241433 3.9582266009852276  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 115 )" class="stroke" mask="url(#u9_img_cl24)" />
+  </g>
+                  </svg>
+                  <div id="u9_text" class="text " style="display:none; visibility: hidden">
+                    <p></p>
+                  </div>
+                </div>
+
+                <!-- Unnamed (Shape) -->
+                <div id="u10" class="ax_default _形状 transition notrs">
+                  <svg data="images/登录界面/u10.svg" id="u10_img" class="img generatedImage">
+
+  <defs>
+    <pattern id="u10_img_bgp" patternUnits="userSpaceOnUse" alignment="0 0" imageRepeat="None" />
+    <mask fill="white" id="u10_img_cl25">
+      <path d="M 482 1.8545812807882385  L 478.0110344827586 1.8545812807882385  L 473.3572413793103 9  L 9.307586206896598 9  L 4.653793103448238 0.9678817733989717  L 0 0.9678817733989717  L 0 11.608275862069036  L 7.31310344827582 19.588571428571413  L 50.52689655172418 19.588571428571413  L 61.828965517241436 12.494975369458075  L 156.89931034482757 12.494975369458075  L 162.88275862068966 16  L 320.4468965517242 16  L 325.1006896551726 12.494975369458075  L 426.81931034482744 12.494975369458075  L 438.78620689655173 19.588571428571413  L 474.68689655172415 19.588571428571413  L 482 10.721576354679883  L 482 1.8545812807882385  Z M 461.39034482758615 16.0417733990148  L 458.73103448275856 16.0417733990148  L 461.39034482758615 12.494975369458075  L 464.0496551724136 12.494975369458075  L 461.39034482758615 16.0417733990148  Z M 466.7089655172413 16.0417733990148  L 464.0496551724136 16.0417733990148  L 466.7089655172413 12.494975369458075  L 469.368275862069 12.494975369458075  L 466.7089655172413 16.0417733990148  Z M 474.68689655172415 12.494975369458075  L 472.0275862068965 16.0417733990148  L 469.368275862069 16.0417733990148  L 472.0275862068965 12.494975369458075  L 474.68689655172415 12.494975369458075  Z M 12.631724137931105 16.0417733990148  L 9.972413793103401 16.0417733990148  L 7.31310344827582 12.494975369458075  L 9.972413793103401 12.494975369458075  L 12.631724137931105 16.0417733990148  Z M 17.950344827586267 16.0417733990148  L 15.291034482758565 16.0417733990148  L 12.631724137931105 12.494975369458075  L 15.291034482758565 12.494975369458075  L 17.950344827586267 16.0417733990148  Z M 23.268965517241433 16.0417733990148  L 20.609655172413728 16.0417733990148  L 17.950344827586267 12.494975369458075  L 20.609655172413728 12.494975369458075  L 23.268965517241433 16.0417733990148  Z " fill-rule="evenodd" />
+    </mask>
+  </defs>
+  <g transform="matrix(1 0 0 1 0 -575 )">
+    <path d="M 482 1.8545812807882385  L 478.0110344827586 1.8545812807882385  L 473.3572413793103 9  L 9.307586206896598 9  L 4.653793103448238 0.9678817733989717  L 0 0.9678817733989717  L 0 11.608275862069036  L 7.31310344827582 19.588571428571413  L 50.52689655172418 19.588571428571413  L 61.828965517241436 12.494975369458075  L 156.89931034482757 12.494975369458075  L 162.88275862068966 16  L 320.4468965517242 16  L 325.1006896551726 12.494975369458075  L 426.81931034482744 12.494975369458075  L 438.78620689655173 19.588571428571413  L 474.68689655172415 19.588571428571413  L 482 10.721576354679883  L 482 1.8545812807882385  Z M 461.39034482758615 16.0417733990148  L 458.73103448275856 16.0417733990148  L 461.39034482758615 12.494975369458075  L 464.0496551724136 12.494975369458075  L 461.39034482758615 16.0417733990148  Z M 466.7089655172413 16.0417733990148  L 464.0496551724136 16.0417733990148  L 466.7089655172413 12.494975369458075  L 469.368275862069 12.494975369458075  L 466.7089655172413 16.0417733990148  Z M 474.68689655172415 12.494975369458075  L 472.0275862068965 16.0417733990148  L 469.368275862069 16.0417733990148  L 472.0275862068965 12.494975369458075  L 474.68689655172415 12.494975369458075  Z M 12.631724137931105 16.0417733990148  L 9.972413793103401 16.0417733990148  L 7.31310344827582 12.494975369458075  L 9.972413793103401 12.494975369458075  L 12.631724137931105 16.0417733990148  Z M 17.950344827586267 16.0417733990148  L 15.291034482758565 16.0417733990148  L 12.631724137931105 12.494975369458075  L 15.291034482758565 12.494975369458075  L 17.950344827586267 16.0417733990148  Z M 23.268965517241433 16.0417733990148  L 20.609655172413728 16.0417733990148  L 17.950344827586267 12.494975369458075  L 20.609655172413728 12.494975369458075  L 23.268965517241433 16.0417733990148  Z " fill-rule="nonzero" fill="rgba(3, 180, 245, 1)" stroke="none" transform="matrix(1 0 0 1 0 575 )" class="fill" />
+    <path d="M 482 1.8545812807882385  L 478.0110344827586 1.8545812807882385  L 473.3572413793103 9  L 9.307586206896598 9  L 4.653793103448238 0.9678817733989717  L 0 0.9678817733989717  L 0 11.608275862069036  L 7.31310344827582 19.588571428571413  L 50.52689655172418 19.588571428571413  L 61.828965517241436 12.494975369458075  L 156.89931034482757 12.494975369458075  L 162.88275862068966 16  L 320.4468965517242 16  L 325.1006896551726 12.494975369458075  L 426.81931034482744 12.494975369458075  L 438.78620689655173 19.588571428571413  L 474.68689655172415 19.588571428571413  L 482 10.721576354679883  L 482 1.8545812807882385  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 575 )" class="stroke" mask="url(#u10_img_cl25)" />
+    <path d="M 461.39034482758615 16.0417733990148  L 458.73103448275856 16.0417733990148  L 461.39034482758615 12.494975369458075  L 464.0496551724136 12.494975369458075  L 461.39034482758615 16.0417733990148  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 575 )" class="stroke" mask="url(#u10_img_cl25)" />
+    <path d="M 466.7089655172413 16.0417733990148  L 464.0496551724136 16.0417733990148  L 466.7089655172413 12.494975369458075  L 469.368275862069 12.494975369458075  L 466.7089655172413 16.0417733990148  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 575 )" class="stroke" mask="url(#u10_img_cl25)" />
+    <path d="M 474.68689655172415 12.494975369458075  L 472.0275862068965 16.0417733990148  L 469.368275862069 16.0417733990148  L 472.0275862068965 12.494975369458075  L 474.68689655172415 12.494975369458075  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 575 )" class="stroke" mask="url(#u10_img_cl25)" />
+    <path d="M 12.631724137931105 16.0417733990148  L 9.972413793103401 16.0417733990148  L 7.31310344827582 12.494975369458075  L 9.972413793103401 12.494975369458075  L 12.631724137931105 16.0417733990148  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 575 )" class="stroke" mask="url(#u10_img_cl25)" />
+    <path d="M 17.950344827586267 16.0417733990148  L 15.291034482758565 16.0417733990148  L 12.631724137931105 12.494975369458075  L 15.291034482758565 12.494975369458075  L 17.950344827586267 16.0417733990148  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 575 )" class="stroke" mask="url(#u10_img_cl25)" />
+    <path d="M 23.268965517241433 16.0417733990148  L 20.609655172413728 16.0417733990148  L 17.950344827586267 12.494975369458075  L 20.609655172413728 12.494975369458075  L 23.268965517241433 16.0417733990148  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(255, 255, 255, 0)" fill="none" transform="matrix(1 0 0 1 0 575 )" class="stroke" mask="url(#u10_img_cl25)" />
+  </g>
+                  </svg>
+                  <div id="u10_text" class="text " style="display:none; visibility: hidden">
+                    <p></p>
+                  </div>
+                </div>
+
+                <!-- Unnamed (Rectangle) -->
+                <div id="u11" class="ax_default _默认样式 transition notrs">
+                  <div id="u11_div" class=""></div>
+                  <div id="u11_text" class="text ">
+                    <p><span>用户登录 </span><span>USER LOGIN</span></p>
+                  </div>
+                </div>
+              </div>
+
+              <!-- 账号输入框 (Group) -->
+              <div id="u12" class="ax_default" data-label="账号输入框" data-left="35" data-top="219" data-width="380" data-height="50" layer-opacity="1">
+
+                <!-- 边框 (Rectangle) -->
+                <div id="u13" class="ax_default _默认样式 transition notrs" data-label="边框">
+                  <div id="u13_div" class=""></div>
+                  <div id="u13_text" class="text " style="display:none; visibility: hidden">
+                    <p></p>
+                  </div>
+                </div>
+
+                <!-- 账号输入框 (Text field) -->
+                <div id="u14" class="ax_default _默认样式 transition notrs" data-label="账号输入框">
+                  <div id="u14_div" class=""></div>
+                  <input id="u14_input" type="text" value="" class="u14_input" maxlength="20"/>
+                </div>
+
+                <!-- 清除 (Rectangle) -->
+                <div id="u15" class="ax_default _默认样式 ax_default_hidden transition notrs" data-label="清除" style="display:none; visibility: hidden">
+                  <div id="u15_div" class=""></div>
+                  <div id="u15_text" class="text ">
+                    <p><i class="fas fa-times"></i></p>
+                  </div>
+                </div>
+
+                <!-- 图标 (Rectangle) -->
+                <div id="u16" class="ax_default _默认样式 transition notrs" data-label="图标">
+                  <div id="u16_div" class=""></div>
+                  <div id="u16_text" class="text ">
+                    <p><i class="fas fa-user"></i></p>
+                  </div>
+                </div>
+              </div>
+
+              <!-- 密码输入框 (Group) -->
+              <div id="u17" class="ax_default" data-label="密码输入框" data-left="35" data-top="289" data-width="380" data-height="50" layer-opacity="1">
+
+                <!-- 边框 (Rectangle) -->
+                <div id="u18" class="ax_default _默认样式 transition notrs" data-label="边框">
+                  <div id="u18_div" class=""></div>
+                  <div id="u18_text" class="text " style="display:none; visibility: hidden">
+                    <p></p>
+                  </div>
+                </div>
+
+                <!-- 密码输入框 (Text field) -->
+                <div id="u19" class="ax_default _默认样式 transition notrs" data-label="密码输入框">
+                  <div id="u19_div" class=""></div>
+                  <input id="u19_input" type="password" value="" class="u19_input" maxlength="20"/>
+                </div>
+
+                <!-- 清除 (Rectangle) -->
+                <div id="u20" class="ax_default _默认样式 ax_default_hidden transition notrs" data-label="清除" style="display:none; visibility: hidden">
+                  <div id="u20_div" class=""></div>
+                  <div id="u20_text" class="text ">
+                    <p><i class="fas fa-times"></i></p>
+                  </div>
+                </div>
+
+                <!-- 图标 (Rectangle) -->
+                <div id="u21" class="ax_default _默认样式 transition notrs" data-label="图标">
+                  <div id="u21_div" class=""></div>
+                  <div id="u21_text" class="text ">
+                    <p><i class="fas fa-key"></i></p>
+                  </div>
+                </div>
+              </div>
+
+              <!-- 校验码输入框 (Group) -->
+              <div id="u22" class="ax_default" data-label="校验码输入框" data-left="35" data-top="359" data-width="270" data-height="50" layer-opacity="1">
+
+                <!-- 边框 (Rectangle) -->
+                <div id="u23" class="ax_default _默认样式 transition notrs" data-label="边框">
+                  <div id="u23_div" class=""></div>
+                  <div id="u23_text" class="text " style="display:none; visibility: hidden">
+                    <p></p>
+                  </div>
+                </div>
+
+                <!-- 校验码输入框 (Text field) -->
+                <div id="u24" class="ax_default _默认样式 transition notrs" data-label="校验码输入框">
+                  <div id="u24_div" class=""></div>
+                  <input id="u24_input" type="text" value="" class="u24_input" maxlength="4"/>
+                </div>
+
+                <!-- 清除 (Rectangle) -->
+                <div id="u25" class="ax_default _默认样式 ax_default_hidden transition notrs" data-label="清除" style="display:none; visibility: hidden">
+                  <div id="u25_div" class=""></div>
+                  <div id="u25_text" class="text ">
+                    <p><i class="fas fa-times"></i></p>
+                  </div>
+                </div>
+
+                <!-- 图标 (Rectangle) -->
+                <div id="u26" class="ax_default _默认样式 transition notrs" data-label="图标">
+                  <div id="u26_div" class=""></div>
+                  <div id="u26_text" class="text ">
+                    <p><i class="fas fa-shield-alt"></i></p>
+                  </div>
+                </div>
+              </div>
+
+              <!-- 校验码 (Dynamic panel) -->
+              <div id="u27" class="ax_default" data-label="校验码">
+                <div id="u27_state0" class="panel_state" data-label="校验码" style="">
+                  <div id="u27_state0_content" class="panel_state_content">
+
+                    <!-- 校验码显示 (Rectangle) -->
+                    <div id="u28" class="ax_default _默认样式 transition notrs" data-label="校验码显示">
+                      <div id="u28_div" class=""></div>
+                      <div id="u28_text" class="text ">
+                        <p><span>ABCD</span></p>
+                      </div>
+                    </div>
+
+                    <!-- 随机字符 (Rectangle) -->
+                    <div id="u29" class="ax_default _默认样式 ax_default_hidden transition notrs" data-label="随机字符" style="display:none; visibility: hidden">
+                      <div id="u29_div" class=""></div>
+                      <div id="u29_text" class="text ">
+                        <p><span>ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789</span></p>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+
+              <!-- 记住密码 (Group) -->
+              <div id="u30" class="ax_default" data-label="记住密码" data-left="35" data-top="409" data-width="164" data-height="50" layer-opacity="1">
+
+                <!-- 文字 (Rectangle) -->
+                <div id="u31" class="ax_default _默认样式 transition notrs" data-label="文字">
+                  <div id="u31_div" class=""></div>
+                  <div id="u31_text" class="text ">
+                    <p><span>记住密码</span></p>
+                  </div>
+                </div>
+
+                <!-- 图标 (Rectangle) -->
+                <div id="u321" class="ax_default _默认样式 transition notrs" data-label="图标">
+                  <div id="u321_div" class=""></div>
+                  <div id="u321_text" class="text" style="">
+                    <p>
+                      <i id="key_code" class="far fa-square"></i>
+                      <i id="key_code2" class="far fa-check-square" style="display:none"></i>
+                    </p>
+                  </div>
+                </div>
+              </div>
+
+              <!-- 忘记密码 (Group) -->
+              <div id="u33" class="ax_default" data-label="忘记密码" data-left="350" data-top="426" data-width="65" data-height="17" layer-opacity="1">
+
+                <!-- Unnamed (Rectangle) -->
+                <div id="u34" class="ax_default _默认样式 transition notrs">
+                  <div id="u34_div" class=""></div>
+                  <div id="u34_text" class="text ">
+                    <p><span>忘记密码?</span></p>
+                  </div>
+                </div>
+
+                <!-- 气泡提示 (Speech bubble) -->
+                <div id="u35" class="ax_default _默认样式 ax_default_hidden transition notrs" data-label="气泡提示" style="display:none; visibility: hidden">
+                  <svg data="images/登录界面/气泡提示_u35.svg" id="u35_img" class="img generatedImage">
+
+  <defs>
+    <pattern id="u35_img_bgp" patternUnits="userSpaceOnUse" alignment="0 0" imageRepeat="None" />
+    <mask fill="white" id="u35_img_cl26">
+      <path d="M 10 54  C 4.477152501692066 54.5623880597015  0 50.08523555800943  0 44.5623880597015  L 0 10  C 0 4.477152501692066  4.477152501692066 0  10 0  L 161 0  C 166.52284749830793 0  171 4.477152501692066  171 10  L 171 44.5623880597015  C 171 50.08523555800943  166.52284749830793 54.5623880597015  161 54  L 149.94166666666678 54  L 140.13333333333338 64.98235489220554  L 129.94166666666678 54  L 10 54  Z " fill-rule="evenodd" />
+    </mask>
+  </defs>
+  <g transform="matrix(1 0 0 1 -246 -356 )">
+    <path d="M 10 54  C 4.477152501692066 54.5623880597015  0 50.08523555800943  0 44.5623880597015  L 0 10  C 0 4.477152501692066  4.477152501692066 0  10 0  L 161 0  C 166.52284749830793 0  171 4.477152501692066  171 10  L 171 44.5623880597015  C 171 50.08523555800943  166.52284749830793 54.5623880597015  161 54  L 149.94166666666678 54  L 140.13333333333338 64.98235489220554  L 129.94166666666678 54  L 10 54  Z " fill-rule="nonzero" fill="rgba(0, 0, 0, 0.8)" stroke="none" transform="matrix(1 0 0 1 246 356 )" class="fill" />
+    <path d="M 10 54  C 4.477152501692066 54.5623880597015  0 50.08523555800943  0 44.5623880597015  L 0 10  C 0 4.477152501692066  4.477152501692066 0  10 0  L 161 0  C 166.52284749830793 0  171 4.477152501692066  171 10  L 171 44.5623880597015  C 171 50.08523555800943  166.52284749830793 54.5623880597015  161 54  L 149.94166666666678 54  L 140.13333333333338 64.98235489220554  L 129.94166666666678 54  L 10 54  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(102, 102, 102, 1)" fill="none" transform="matrix(1 0 0 1 246 356 )" class="stroke" mask="url(#u35_img_cl26)" />
+  </g>
+                  </svg>
+                  <div id="u35_text" class="text ">
+                    <p><span>请联系管理员重置密码</span></p><p><span>电话:400-888-8888</span></p>
+                  </div>
+                </div>
+              </div>
+
+              <!-- 登录按钮 (Group) -->
+              <div id="u36" class="ax_default" data-label="登录按钮" data-left="35" data-top="458" data-width="380" data-height="50" layer-opacity="1">
+
+                <!-- 登录按纽 (Rectangle) -->
+                <div id="u37" class="ax_default _默认样式 transition notrs" data-label="登录按纽">
+                  <div id="u37_div" class=""></div>
+                  <div id="u37_text" class="text ">
+                    <p><span>登录</span></p>
+                  </div>
+                </div>
+
+                <!-- 加载图标 (SVG) -->
+                <div id="u38" class="ax_default _默认样式 ax_default_hidden transition notrs" data-label="加载图标" style="display:none; visibility: hidden">
+                  <img id="u38_img" class="img " src="images/登录界面/加载图标_u38.svg"/>
+                  <div id="u38_text" class="text " style="display:none; visibility: hidden">
+                    <p></p>
+                  </div>
+                </div>
+              </div>
+
+              <!-- 警告提示 (Dynamic panel) -->
+              <div id="u39" class="ax_default ax_default_hidden" data-label="警告提示" style="display:none; visibility: hidden">
+                <div id="u39_state0" class="panel_state" data-label="请填写用户名称" style="">
+                  <div id="u39_state0_content" class="panel_state_content">
+
+                    <!-- Unnamed (Rectangle) -->
+                    <div id="u40" class="ax_default _默认样式 transition notrs">
+                      <div id="u40_div" class=""></div>
+                      <div id="u40_text" class="text ">
+                        <p><span style="font-family:'Font Awesome 5 Pro', sans-serif;font-weight:400;"></span><span style="font-family:'微软雅黑', sans-serif;font-weight:400;"> 请填写用户账号</span></p>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                <div id="u39_state1" class="panel_state" data-label="请填写登录密码" style="visibility: hidden;">
+                  <div id="u39_state1_content" class="panel_state_content">
+
+                    <!-- Unnamed (Rectangle) -->
+                    <div id="u41" class="ax_default _默认样式 transition notrs">
+                      <div id="u41_div" class=""></div>
+                      <div id="u41_text" class="text ">
+                        <p><span style="font-family:'Font Awesome 5 Pro', sans-serif;font-weight:400;"></span><span style="font-family:'微软雅黑', sans-serif;font-weight:400;"> 请填写登录密码</span></p>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                <div id="u39_state2" class="panel_state" data-label="请填写校验码" style="visibility: hidden;">
+                  <div id="u39_state2_content" class="panel_state_content">
+
+                    <!-- Unnamed (Rectangle) -->
+                    <div id="u42" class="ax_default _默认样式 transition notrs">
+                      <div id="u42_div" class=""></div>
+                      <div id="u42_text" class="text ">
+                        <p><span style="font-family:'Font Awesome 5 Pro', sans-serif;font-weight:400;"></span><span style="font-family:'微软雅黑', sans-serif;font-weight:400;"> 请填写校验码</span></p>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                <div id="u39_state3" class="panel_state" data-label="用户名或密码不正确" style="visibility: hidden;">
+                  <div id="u39_state3_content" class="panel_state_content">
+
+                    <!-- Unnamed (Rectangle) -->
+                    <div id="u43" class="ax_default _默认样式 transition notrs">
+                      <div id="u43_div" class=""></div>
+                      <div id="u43_text" class="text ">
+                        <p><span style="font-family:'Font Awesome 5 Pro', sans-serif;font-weight:400;"></span><span style="font-family:'微软雅黑', sans-serif;font-weight:400;"> 用户名或密码不正确</span></p>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                <div id="u39_state4" class="panel_state" data-label="校验码不正确" style="visibility: hidden;">
+                  <div id="u39_state4_content" class="panel_state_content">
+
+                    <!-- Unnamed (Rectangle) -->
+                    <div id="u44" class="ax_default _默认样式 transition notrs">
+                      <div id="u44_div" class=""></div>
+                      <div id="u44_text" class="text ">
+                        <p><span style="font-family:'Font Awesome 5 Pro', sans-serif;font-weight:400;"></span><span style="font-family:'微软雅黑', sans-serif;font-weight:400;"> 确校验码不正确,请重新输入</span></p>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+
+              <!-- 登录说明 (Group) -->
+              <div id="u45" class="ax_default" data-label="登录说明" data-left="420" data-top="141" data-width="52" data-height="17" layer-opacity="1">
+
+                <!-- Unnamed (Rectangle) -->
+                <div id="u46" class="ax_default _默认样式 transition notrs">
+                  <div id="u46_div" class=""></div>
+                  <div id="u46_text" class="text ">
+                    <p><span>登录说明</span></p>
+                  </div>
+                </div>
+
+                <!-- 气泡提示 (Group) -->
+                <div id="u47" class="ax_default ax_default_hidden" data-label="气泡提示" style="display:none; visibility: hidden" data-left="292" data-top="161" data-width="182" data-height="90" layer-opacity="1">
+
+                  <!-- 背景 (Shape) -->
+                  <div id="u48" class="ax_default _默认样式 transition notrs" data-label="背景">
+                    <svg data="images/登录界面/背景_u48.svg" id="u48_img" class="img generatedImage">
+
+  <defs>
+    <pattern id="u48_img_bgp" patternUnits="userSpaceOnUse" alignment="0 0" imageRepeat="None" />
+    <mask fill="white" id="u48_img_cl27">
+      <path d="M 10.64327485380116 11  C 4.765156463789225 11.094392652123986  0 17.569043962263294  0 25.555931113662467  L 0 75.53846153846155  C 0 83.52534868986072  4.765156463789225 90  10.64327485380116 90  L 171.35672514619887 90  C 177.23484353621075 90  182 83.52534868986072  182 75.53846153846155  L 182 25.555931113662467  C 182 17.569043962263294  177.23484353621075 11.094392652123986  171.35672514619887 11  L 160.71428571428572 11  L 152.42857142857144 0  L 144.14285714285717 11  L 10.64327485380116 11  Z " fill-rule="evenodd" />
+    </mask>
+  </defs>
+  <g transform="matrix(1 0 0 1 -292 -161 )">
+    <path d="M 10.64327485380116 11  C 4.765156463789225 11.094392652123986  0 17.569043962263294  0 25.555931113662467  L 0 75.53846153846155  C 0 83.52534868986072  4.765156463789225 90  10.64327485380116 90  L 171.35672514619887 90  C 177.23484353621075 90  182 83.52534868986072  182 75.53846153846155  L 182 25.555931113662467  C 182 17.569043962263294  177.23484353621075 11.094392652123986  171.35672514619887 11  L 160.71428571428572 11  L 152.42857142857144 0  L 144.14285714285717 11  L 10.64327485380116 11  Z " fill-rule="nonzero" fill="rgba(0, 0, 0, 0.8)" stroke="none" transform="matrix(1 0 0 1 292 161 )" class="fill" />
+    <path d="M 10.64327485380116 11  C 4.765156463789225 11.094392652123986  0 17.569043962263294  0 25.555931113662467  L 0 75.53846153846155  C 0 83.52534868986072  4.765156463789225 90  10.64327485380116 90  L 171.35672514619887 90  C 177.23484353621075 90  182 83.52534868986072  182 75.53846153846155  L 182 25.555931113662467  C 182 17.569043962263294  177.23484353621075 11.094392652123986  171.35672514619887 11  L 160.71428571428572 11  L 152.42857142857144 0  L 144.14285714285717 11  L 10.64327485380116 11  Z " stroke-width="0" stroke-dasharray="0" stroke="rgba(102, 102, 102, 1)" fill="none" transform="matrix(1 0 0 1 292 161 )" class="stroke" mask="url(#u48_img_cl27)" />
+  </g>
+                    </svg>
+                    <div id="u48_text" class="text " style="display:none; visibility: hidden">
+                      <p></p>
+                    </div>
+                  </div>
+
+                  <!-- 文字 (Rectangle) -->
+                  <div id="u49" class="ax_default _默认样式 transition notrs" data-label="文字">
+                    <div id="u49_div" class=""></div>
+                    <div id="u49_text" class="text ">
+                      <p style="font-size:14px;"><span style="font-family:'微软雅黑', sans-serif;font-weight:400;">需验证账号密码完成登录</span></p><p style="font-size:12px;"><span style="font-family:'微软雅黑', sans-serif;font-weight:400;">账号:ZW</span></p><p style="font-size:12px;"><span style="font-family:'微软雅黑', sans-serif;font-weight:400;">密码:12345678</span></p>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <script src="resources/scripts/axure/ios.js"></script>
+  <script>
+    document.getElementById("u37").addEventListener("click", function () {
+      // 获取账号、密码和验证码输入框的值
+      var username = document.getElementById("u14_input").value;
+      var password = document.getElementById("u19_input").value;
+      var verificationCodeInput = document.getElementById("u24_input").value;
+
+      // 获取当前显示的验证码
+      var correctVerificationCode = document.getElementById("u28_text").innerText.trim();
+
+      // 验证字段是否为空
+      if (!username) {
+        showWarningMessage("请填写用户名称");
+        return;
+      }
+
+      if (!password) {
+        showWarningMessage("请填写登录密码");
+        return;
+      }
+
+      if (!verificationCodeInput) {
+        showWarningMessage("请填写校验码");
+        return;
+      }
+
+      // 验证账号密码是否正确
+      if (username === "ZW" && password === "12345678") {
+        // 验证验证码是否正确
+        if (verificationCodeInput === correctVerificationCode) {
+          // 跳转到目标页面
+          setTimeout(function () {
+            window.location.href = "入口界面.html"; // 替换为实际的页面 URL
+          }, 2000);
+        } else {
+          showWarningMessage("校验码不正确");
+        }
+      } else {
+        showWarningMessage("用户名或密码不正确");
+      }
+    });
+
+    // 显示警告提示的函数
+    function showWarningMessage(message) {
+      var warningPanel = document.getElementById("u39");
+      var warningText = warningPanel.querySelector(".text");
+
+      // 设置提示信息
+      warningText.innerHTML = '<p><span style="font-family:\'Font Awesome 5 Pro\', sans-serif;font-weight:400;"></span><span style="font-family:\'微软雅黑\', sans-serif;font-weight:400;"> ' + message + '</span></p>';
+
+      // 显示警告面板
+      warningPanel.style.display = "block";
+
+      // 自动隐藏警告面板
+      setTimeout(function () {
+        warningPanel.style.display = "none";
+      }, 5000);
+    }
+
+    // 页面加载时读取 localStorage 的状态
+        window.addEventListener("load", function () {
+        var isChecked = localStorage.getItem("rememberPassword") === "true";
+
+        if (isChecked) {
+        document.getElementById("key_code").style.display = "none";
+        document.getElementById("key_code2").style.display = "";
+      } else {
+        document.getElementById("key_code").style.display = "";
+        document.getElementById("key_code2").style.display = "none";
+      }
+      });
+
+        // 监听 key_code 图标点击事件
+        document.getElementById("key_code").addEventListener("click", function () {
+        var uncheckedIcon = document.getElementById("key_code");
+        var checkedIcon = document.getElementById("key_code2");
+
+        // 切换显示状态
+        if (uncheckedIcon.style.display === "none") {
+        uncheckedIcon.style.display = "";        // 显示 fa-square
+        checkedIcon.style.display = "none";     // 隐藏 fa-check-square
+        localStorage.setItem("rememberPassword", "false"); // 存储状态
+      } else {
+        uncheckedIcon.style.display = "none";   // 隐藏 fa-square
+        checkedIcon.style.display = "";         // 显示 fa-check-square
+        localStorage.setItem("rememberPassword", "true");  // 存储状态
+      }
+      });
+    </script>
+
+  </body>
+</html>

+ 373 - 0
license.md

@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  This Source Code Form is subject to the terms of the Mozilla Public
+  License, v. 2.0. If a copy of the MPL was not distributed with this
+  file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+  This Source Code Form is "Incompatible With Secondary Licenses", as
+  defined by the Mozilla Public License, v. 2.0.

+ 19 - 0
mock/controller/ad.js

@@ -0,0 +1,19 @@
+const data = [
+  {
+    title: "vue-admin-beautiful-pro beta版本已发布,点我提前体验",
+    url: "https://chu1204505056.gitee.io/vue-admin-beautiful-pro/#/index",
+  },
+];
+module.exports = [
+  {
+    url: "/ad/getList",
+    type: "get",
+    response() {
+      return {
+        code: 200,
+        msg: "success",
+        data,
+      };
+    },
+  },
+];

+ 87 - 0
mock/controller/blacklist.js

@@ -0,0 +1,87 @@
+const data = [
+  {
+    name: "奉/fendou飘逸的梦",
+    qq: "812770127",
+    excuse: "上来就开骂,不可原谅",
+  },
+  {
+    name: "江荻",
+    qq: "2324945654",
+    excuse: "上来就开骂,不可原谅",
+  },
+  {
+    name: "Diamond",
+    qq: "494904935",
+    excuse: "跟我道歉可以选择原谅",
+  },
+  {
+    name: "Mr、无涯",
+    qq: "2198457489",
+    excuse: "已原谅",
+  },
+  {
+    name: "玩世不恭丶江小白",
+    qq: "1779263221",
+    excuse: "睁眼说瞎话",
+  },
+  {
+    name: "福州客家网络科技有限公司(潘芳林等兄弟二人)",
+    qq: "1409198410、1778486252",
+    excuse:
+      "剽窃、破解框架授权并发布到网上还伪装成善人,公开道歉并尊重我的劳动成果可以选择原谅",
+  },
+  {
+    name: "willina",
+    qq: "405522648",
+    excuse:
+      "上来就开骂道:You and your git submit are just a rubbish,不可原谅",
+  },
+  {
+    name: "7(赵海鹏)",
+    qq: "252334666",
+    excuse: "欺骗两个善良的小姑娘,做完项目不付70%的尾款,强烈抵制",
+  },
+  {
+    name: "生活,一半记忆.一半继续",
+    qq: "252667193",
+    excuse: "30多岁,不学无术,造谣抹黑,不可原谅",
+  },
+  {
+    name: "AIRLOO",
+    qq: "5971794",
+    excuse: "已原谅",
+  },
+  {
+    name: "master Z",
+    qq: "1832819123",
+    excuse: "不尊重别人的劳动成果,认为开源就得无偿替他服务,不可原谅",
+  },
+  {
+    name: "想象中。。。",
+    qq: "329492979",
+    excuse: "不尊重别人的劳动成果,认为开源就得无偿替他服务,不可原谅",
+  },
+  {
+    name: "苏潍—菏泽微智科技",
+    qq: "328580081",
+    excuse: "无言以对",
+  },
+  {
+    name: "罗阳",
+    qq: "1320168680",
+    excuse: "不尊重别人的劳动成果,认为开源就得无偿替他服务,不可原谅",
+  },
+];
+module.exports = [
+  {
+    url: "/blacklist/getList",
+    type: "post",
+    response() {
+      return {
+        code: 200,
+        msg: "success",
+        data,
+      };
+    },
+  },
+];

+ 328 - 0
mock/controller/colorfulIcon.js

@@ -0,0 +1,328 @@
+const data = [
+  "alphabetical_sorting",
+  "advance",
+  "address_book",
+  "alphabetical_sorting",
+  "advertising",
+  "alarm_clock",
+  "area_chart",
+  "approval",
+  "answers",
+  "approve",
+  "assistant",
+  "audio_file",
+  "automotive",
+  "automatic",
+  "bad_decision",
+  "bar_chart",
+  "bearish",
+  "biomass",
+  "biohazard",
+  "binoculars",
+  "bookmark",
+  "briefcase",
+  "biotech",
+  "broken_link",
+  "business",
+  "bullish",
+  "business_contact",
+  "businesswoman",
+  "cable_release",
+  "calculator",
+  "businessman",
+  "calendar",
+  "butting_in",
+  "call_transfer",
+  "callback",
+  "camcorder",
+  "camera",
+  "camcorder_pro",
+  "cancel",
+  "camera_addon",
+  "camera_identificatio",
+  "capacitor",
+  "candle_sticks",
+  "checkmark",
+  "circuit",
+  "charge_battery",
+  "clear_filters",
+  "clapperboard",
+  "clock",
+  "close_up_mode",
+  "collaboration",
+  "cell_phone",
+  "collapse",
+  "collect",
+  "cloth",
+  "combo_chart",
+  "comments",
+  "conference_call",
+  "compact_camera",
+  "contacts",
+  "copyleft",
+  "copyright",
+  "crystal_oscillator",
+  "cursor",
+  "currency_exchange",
+  "customer_support",
+  "dam",
+  "data_backup",
+  "data_configuration",
+  "data_encryption",
+  "data_protection",
+  "data_recovery",
+  "database",
+  "data_sheet",
+  "debt",
+  "decision",
+  "delete_column",
+  "delete_database",
+  "department",
+  "delete_row",
+  "deployment",
+  "dislike",
+  "disapprove",
+  "disclaimer",
+  "display",
+  "document",
+  "do_not_insert",
+  "do_not_mix",
+  "do_not_inhale",
+  "donate",
+  "down",
+  "doughnut_chart",
+  "down_left",
+  "down_right",
+  "download",
+  "edit_image",
+  "electrical_sensor",
+  "electrical_threshold",
+  "electricity",
+  "electro_devices",
+  "electronics",
+  "empty_battery",
+  "empty_filter",
+  "empty_trash",
+  "end_call",
+  "engineering",
+  "entering_heaven_aliv",
+  "expand",
+  "export",
+  "expired",
+  "factory",
+  "factory_breakdown",
+  "external",
+  "faq",
+  "feed_in",
+  "file",
+  "feedback",
+  "film",
+  "filled_filter",
+  "filing_cabinet",
+  "film_reel",
+  "flash_auto",
+  "fine_print",
+  "flash_off",
+  "flash_on",
+  "flow_chart",
+  "folder",
+  "frame",
+  "full_battery",
+  "full_trash",
+  "gallery",
+  "generic_sorting_asc",
+  "generic_sorting_desc",
+  "genealogy",
+  "globe",
+  "good_decision",
+  "headset",
+  "grid",
+  "graduation_cap",
+  "heat_map",
+  "high_priority",
+  "high_battery",
+  "image_file",
+  "home",
+  "idea",
+  "import",
+  "in_transit",
+  "integrated_webcam",
+  "inspection",
+  "invite",
+  "internal",
+  "ipad",
+  "info",
+  "iphone",
+  "kindle",
+  "key",
+  "landscape",
+  "left",
+  "left_down",
+  "left_up",
+  "leave",
+  "like_placeholder",
+  "light_at_the_end_of_",
+  "library",
+  "line_chart",
+  "link",
+  "like",
+  "lock",
+  "list",
+  "lock_landscape",
+  "low_battery",
+  "lock_portrait",
+  "low_priority",
+  "make_decision",
+  "medium_priority",
+  "manager",
+  "menu",
+  "middle_battery",
+  "minus",
+  "missed_call",
+  "mind_map",
+  "mms",
+  "multiple_cameras",
+  "money_transfer",
+  "music",
+  "multiple_devices",
+  "multiple_smartphones",
+  "multiple_inputs",
+  "negative_dynamic",
+  "neutral_decision",
+  "night_landscape",
+  "news",
+  "neutral_trading",
+  "night_portrait",
+  "no_idea",
+  "next",
+  "no_video",
+  "nook",
+  "ok",
+  "org_unit",
+  "opened_folder",
+  "old_time_camera",
+  "online_support",
+  "organization",
+  "package",
+  "paid",
+  "parallel_tasks",
+  "overtime",
+  "panorama",
+  "phone",
+  "phone_android",
+  "photo_reel",
+  "pie_chart",
+  "picture",
+  "planner",
+  "plus",
+  "podium_with_audience",
+  "podium_without_speak",
+  "podium_with_speaker",
+  "previous",
+  "portrait_mode",
+  "positive_dynamic",
+  "privacy",
+  "process",
+  "puzzle",
+  "questions",
+  "print",
+  "radar_plot",
+  "rating",
+  "ratings",
+  "reading",
+  "redo",
+  "reading_ebook",
+  "refresh",
+  "registered_trademark",
+  "right",
+  "reuse",
+  "remove_image",
+  "right_down",
+  "right_up",
+  "rotate_to_portrait",
+  "rules",
+  "rotate_camera",
+  "rotate_to_landscape",
+  "ruler",
+  "scatter_plot",
+  "search",
+  "safe",
+  "self_service_kiosk",
+  "selfie",
+  "serial_tasks",
+  "sales_performance",
+  "settings",
+  "services",
+  "share",
+  "shipped",
+  "sim_card",
+  "shop",
+  "service_mark",
+  "sim_card_chip",
+  "signature",
+  "smartphone_tablet",
+  "sound_recording_copy",
+  "sms",
+  "speaker",
+  "slr_back_side",
+  "start",
+  "stack_of_photos",
+  "statistics",
+  "sports_mode",
+  "support",
+  "synchronize",
+  "switch_camera",
+  "survey",
+  "tablet_android",
+  "template",
+  "trademark",
+  "todo_list",
+  "touchscreen_smartpho",
+  "timeline",
+  "tree_structure",
+  "undo",
+  "up_left",
+  "two_smartphones",
+  "unlock",
+  "up",
+  "up_right",
+  "upload",
+  "video_call",
+  "video_file",
+  "view_details",
+  "video_projector",
+  "vip",
+  "voice_presentation",
+  "webcam",
+  "voicemail",
+  "workflow",
+  "about",
+  "accept_database",
+  "add_image",
+  "add_column",
+  "add_database",
+  "add_row",
+];
+module.exports = [
+  {
+    url: "/colorfulIcon/getList",
+    type: "post",
+    response(config) {
+      const { title, pageNo = 1, pageSize = 72 } = config.body;
+      let mockList = data.filter((item) => {
+        if (title && item.indexOf(title) < 0) return false;
+        return true;
+      });
+      const pageList = mockList.filter(
+        (item, index) =>
+          index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
+      );
+      return {
+        code: 200,
+        msg: "success",
+        totalCount: mockList.length,
+        data: pageList,
+      };
+    },
+  },
+];

+ 42 - 0
mock/controller/goodsDetail.js

@@ -0,0 +1,42 @@
+const { mock } = require("mockjs");
+
+module.exports = [
+  {
+    url: "/goodsDetail/getList",
+    type: "post",
+    response(config) {
+      return {
+        code: 200,
+        msg: "success",
+        totalCount: 999,
+        data: mock({
+          "data|10": [
+            {
+              id: "@id",
+            },
+          ],
+        }).data,
+      };
+    },
+  },
+  {
+    url: "/goodsDetail/doEdit",
+    type: "post",
+    response(config) {
+      return {
+        code: 200,
+        msg: "模拟保存成功",
+      };
+    },
+  },
+  {
+    url: "/goodsDetail/doDelete",
+    type: "post",
+    response(config) {
+      return {
+        code: 200,
+        msg: "模拟删除成功",
+      };
+    },
+  },
+];

+ 43 - 0
mock/controller/goodsList.js

@@ -0,0 +1,43 @@
+const { mock } = require("mockjs");
+
+const List = [];
+const count = 999;
+let num = 0;
+for (let i = 0; i < count; i++) {
+  List.push(
+    mock({
+      uuid: "@uuid",
+      image: `https://picsum.photos/300/600?random=${num++}`,
+      title: "@ctitle",
+      description: "@csentence",
+      link: "https://www.baidu.com",
+      price: "@integer(100, 500)",
+      "status|1": [1, 0],
+      "isRecommend|1": [1, 0],
+    })
+  );
+}
+
+module.exports = [
+  {
+    url: "/goodsList/getList",
+    type: "post",
+    response(config) {
+      const { title = "", pageNo = 1, pageSize = 20 } = config.body;
+      let mockList = List.filter((item) => {
+        if (title && item.title.indexOf(title) < 0) return false;
+        return true;
+      });
+      const pageList = mockList.filter(
+        (item, index) =>
+          index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
+      );
+      return {
+        code: 200,
+        msg: "success",
+        totalCount: count,
+        data: pageList,
+      };
+    },
+  },
+];

+ 989 - 0
mock/controller/icon.js

@@ -0,0 +1,989 @@
+const data = [
+  "ad",
+  "address-book",
+  "address-card",
+  "adjust",
+  "air-freshener",
+  "align-center",
+  "align-justify",
+  "align-left",
+  "align-right",
+  "allergies",
+  "ambulance",
+  "american-sign-language-interpreting",
+  "anchor",
+  "angle-double-down",
+  "angle-double-left",
+  "angle-double-right",
+  "angle-double-up",
+  "angle-down",
+  "angle-left",
+  "angle-right",
+  "angle-up",
+  "angry",
+  "ankh",
+  "apple-alt",
+  "archive",
+  "archway",
+  "arrow-alt-circle-down",
+  "arrow-alt-circle-left",
+  "arrow-alt-circle-right",
+  "arrow-alt-circle-up",
+  "arrow-circle-down",
+  "arrow-circle-left",
+  "arrow-circle-right",
+  "arrow-circle-up",
+  "arrow-down",
+  "arrow-left",
+  "arrow-right",
+  "arrow-up",
+  "arrows-alt",
+  "arrows-alt-h",
+  "arrows-alt-v",
+  "assistive-listening-systems",
+  "asterisk",
+  "at",
+  "atlas",
+  "atom",
+  "audio-description",
+  "award",
+  "baby",
+  "baby-carriage",
+  "backspace",
+  "backward",
+  "bacon",
+  "bahai",
+  "balance-scale",
+  "balance-scale-left",
+  "balance-scale-right",
+  "ban",
+  "band-aid",
+  "barcode",
+  "bars",
+  "baseball-ball",
+  "basketball-ball",
+  "bath",
+  "battery-empty",
+  "battery-full",
+  "battery-half",
+  "battery-quarter",
+  "battery-three-quarters",
+  "bed",
+  "beer",
+  "bell",
+  "bell-slash",
+  "bezier-curve",
+  "bible",
+  "bicycle",
+  "biking",
+  "binoculars",
+  "biohazard",
+  "birthday-cake",
+  "blender",
+  "blender-phone",
+  "blind",
+  "blog",
+  "bold",
+  "bolt",
+  "bomb",
+  "bone",
+  "bong",
+  "book",
+  "book-dead",
+  "book-medical",
+  "book-open",
+  "book-reader",
+  "bookmark",
+  "border-all",
+  "border-none",
+  "border-style",
+  "bowling-ball",
+  "box",
+  "box-open",
+  "boxes",
+  "braille",
+  "brain",
+  "bread-slice",
+  "briefcase",
+  "briefcase-medical",
+  "broadcast-tower",
+  "broom",
+  "brush",
+  "bug",
+  "building",
+  "bullhorn",
+  "bullseye",
+  "burn",
+  "bus",
+  "bus-alt",
+  "business-time",
+  "calculator",
+  "calendar",
+  "calendar-alt",
+  "calendar-check",
+  "calendar-day",
+  "calendar-minus",
+  "calendar-plus",
+  "calendar-times",
+  "calendar-week",
+  "camera",
+  "camera-retro",
+  "campground",
+  "candy-cane",
+  "cannabis",
+  "capsules",
+  "car",
+  "car-alt",
+  "car-battery",
+  "car-crash",
+  "car-side",
+  "caravan",
+  "caret-down",
+  "caret-left",
+  "caret-right",
+  "caret-square-down",
+  "caret-square-left",
+  "caret-square-right",
+  "caret-square-up",
+  "caret-up",
+  "carrot",
+  "cart-arrow-down",
+  "cart-plus",
+  "cash-register",
+  "cat",
+  "certificate",
+  "chair",
+  "chalkboard",
+  "chalkboard-teacher",
+  "charging-station",
+  "chart-area",
+  "chart-bar",
+  "chart-line",
+  "chart-pie",
+  "check",
+  "check-circle",
+  "check-double",
+  "check-square",
+  "cheese",
+  "chess",
+  "chess-bishop",
+  "chess-board",
+  "chess-king",
+  "chess-knight",
+  "chess-pawn",
+  "chess-queen",
+  "chess-rook",
+  "chevron-circle-down",
+  "chevron-circle-left",
+  "chevron-circle-right",
+  "chevron-circle-up",
+  "chevron-down",
+  "chevron-left",
+  "chevron-right",
+  "chevron-up",
+  "child",
+  "church",
+  "circle",
+  "circle-notch",
+  "city",
+  "clinic-medical",
+  "clipboard",
+  "clipboard-check",
+  "clipboard-list",
+  "clock",
+  "clone",
+  "closed-captioning",
+  "cloud",
+  "cloud-download-alt",
+  "cloud-meatball",
+  "cloud-moon",
+  "cloud-moon-rain",
+  "cloud-rain",
+  "cloud-showers-heavy",
+  "cloud-sun",
+  "cloud-sun-rain",
+  "cloud-upload-alt",
+  "cocktail",
+  "code",
+  "code-branch",
+  "coffee",
+  "cog",
+  "cogs",
+  "coins",
+  "columns",
+  "comment",
+  "comment-alt",
+  "comment-dollar",
+  "comment-dots",
+  "comment-medical",
+  "comment-slash",
+  "comments",
+  "comments-dollar",
+  "compact-disc",
+  "compass",
+  "compress",
+  "compress-alt",
+  "compress-arrows-alt",
+  "concierge-bell",
+  "cookie",
+  "cookie-bite",
+  "copy",
+  "copyright",
+  "couch",
+  "credit-card",
+  "crop",
+  "crop-alt",
+  "cross",
+  "crosshairs",
+  "crow",
+  "crown",
+  "crutch",
+  "cube",
+  "cubes",
+  "cut",
+  "database",
+  "deaf",
+  "democrat",
+  "desktop",
+  "dharmachakra",
+  "diagnoses",
+  "dice",
+  "dice-d20",
+  "dice-d6",
+  "dice-five",
+  "dice-four",
+  "dice-one",
+  "dice-six",
+  "dice-three",
+  "dice-two",
+  "digital-tachograph",
+  "directions",
+  "divide",
+  "dizzy",
+  "dna",
+  "dog",
+  "dollar-sign",
+  "dolly",
+  "dolly-flatbed",
+  "donate",
+  "door-closed",
+  "door-open",
+  "dot-circle",
+  "dove",
+  "download",
+  "drafting-compass",
+  "dragon",
+  "draw-polygon",
+  "drum",
+  "drum-steelpan",
+  "drumstick-bite",
+  "dumbbell",
+  "dumpster",
+  "dumpster-fire",
+  "dungeon",
+  "edit",
+  "egg",
+  "eject",
+  "ellipsis-h",
+  "ellipsis-v",
+  "envelope",
+  "envelope-open",
+  "envelope-open-text",
+  "envelope-square",
+  "equals",
+  "eraser",
+  "ethernet",
+  "euro-sign",
+  "exchange-alt",
+  "exclamation",
+  "exclamation-circle",
+  "exclamation-triangle",
+  "expand",
+  "expand-alt",
+  "expand-arrows-alt",
+  "external-link-alt",
+  "external-link-square-alt",
+  "eye",
+  "eye-dropper",
+  "eye-slash",
+  "fan",
+  "fast-backward",
+  "fast-forward",
+  "fax",
+  "feather",
+  "feather-alt",
+  "female",
+  "fighter-jet",
+  "file",
+  "file-alt",
+  "file-archive",
+  "file-audio",
+  "file-code",
+  "file-contract",
+  "file-csv",
+  "file-download",
+  "file-excel",
+  "file-export",
+  "file-image",
+  "file-import",
+  "file-invoice",
+  "file-invoice-dollar",
+  "file-medical",
+  "file-medical-alt",
+  "file-pdf",
+  "file-powerpoint",
+  "file-prescription",
+  "file-signature",
+  "file-upload",
+  "file-video",
+  "file-word",
+  "fill",
+  "fill-drip",
+  "film",
+  "filter",
+  "fingerprint",
+  "fire",
+  "fire-alt",
+  "fire-extinguisher",
+  "first-aid",
+  "fish",
+  "fist-raised",
+  "flag",
+  "flag-checkered",
+  "flag-usa",
+  "flask",
+  "flushed",
+  "folder",
+  "folder-minus",
+  "folder-open",
+  "folder-plus",
+  "font",
+  "football-ball",
+  "forward",
+  "frog",
+  "frown",
+  "frown-open",
+  "funnel-dollar",
+  "futbol",
+  "gamepad",
+  "gas-pump",
+  "gavel",
+  "gem",
+  "genderless",
+  "ghost",
+  "gift",
+  "gifts",
+  "glass-cheers",
+  "glass-martini",
+  "glass-martini-alt",
+  "glass-whiskey",
+  "glasses",
+  "globe",
+  "globe-africa",
+  "globe-americas",
+  "globe-asia",
+  "globe-europe",
+  "golf-ball",
+  "gopuram",
+  "graduation-cap",
+  "greater-than",
+  "greater-than-equal",
+  "grimace",
+  "grin",
+  "grin-alt",
+  "grin-beam",
+  "grin-beam-sweat",
+  "grin-hearts",
+  "grin-squint",
+  "grin-squint-tears",
+  "grin-stars",
+  "grin-tears",
+  "grin-tongue",
+  "grin-tongue-squint",
+  "grin-tongue-wink",
+  "grin-wink",
+  "grip-horizontal",
+  "grip-lines",
+  "grip-lines-vertical",
+  "grip-vertical",
+  "guitar",
+  "h-square",
+  "hamburger",
+  "hammer",
+  "hamsa",
+  "hand-holding",
+  "hand-holding-heart",
+  "hand-holding-usd",
+  "hand-lizard",
+  "hand-middle-finger",
+  "hand-paper",
+  "hand-peace",
+  "hand-point-down",
+  "hand-point-left",
+  "hand-point-right",
+  "hand-point-up",
+  "hand-pointer",
+  "hand-rock",
+  "hand-scissors",
+  "hand-spock",
+  "hands",
+  "hands-helping",
+  "handshake",
+  "hanukiah",
+  "hard-hat",
+  "hashtag",
+  "hat-cowboy",
+  "hat-cowboy-side",
+  "hat-wizard",
+  "hdd",
+  "heading",
+  "headphones",
+  "headphones-alt",
+  "headset",
+  "heart",
+  "heart-broken",
+  "heartbeat",
+  "helicopter",
+  "highlighter",
+  "hiking",
+  "hippo",
+  "history",
+  "hockey-puck",
+  "holly-berry",
+  "home",
+  "horse",
+  "horse-head",
+  "hospital",
+  "hospital-alt",
+  "hospital-symbol",
+  "hot-tub",
+  "hotdog",
+  "hotel",
+  "hourglass",
+  "hourglass-end",
+  "hourglass-half",
+  "hourglass-start",
+  "house-damage",
+  "hryvnia",
+  "i-cursor",
+  "ice-cream",
+  "icicles",
+  "icons",
+  "id-badge",
+  "id-card",
+  "id-card-alt",
+  "igloo",
+  "image",
+  "images",
+  "inbox",
+  "indent",
+  "industry",
+  "infinity",
+  "info",
+  "info-circle",
+  "italic",
+  "jedi",
+  "joint",
+  "journal-whills",
+  "kaaba",
+  "key",
+  "keyboard",
+  "khanda",
+  "kiss",
+  "kiss-beam",
+  "kiss-wink-heart",
+  "kiwi-bird",
+  "landmark",
+  "language",
+  "laptop",
+  "laptop-code",
+  "laptop-medical",
+  "laugh",
+  "laugh-beam",
+  "laugh-squint",
+  "laugh-wink",
+  "layer-group",
+  "leaf",
+  "lemon",
+  "less-than",
+  "less-than-equal",
+  "level-down-alt",
+  "level-up-alt",
+  "life-ring",
+  "lightbulb",
+  "link",
+  "lira-sign",
+  "list",
+  "list-alt",
+  "list-ol",
+  "list-ul",
+  "location-arrow",
+  "lock",
+  "lock-open",
+  "long-arrow-alt-down",
+  "long-arrow-alt-left",
+  "long-arrow-alt-right",
+  "long-arrow-alt-up",
+  "low-vision",
+  "luggage-cart",
+  "magic",
+  "magnet",
+  "mail-bulk",
+  "male",
+  "map",
+  "map-marked",
+  "map-marked-alt",
+  "map-marker",
+  "map-marker-alt",
+  "map-pin",
+  "map-signs",
+  "marker",
+  "mars",
+  "mars-double",
+  "mars-stroke",
+  "mars-stroke-h",
+  "mars-stroke-v",
+  "mask",
+  "medal",
+  "medkit",
+  "meh",
+  "meh-blank",
+  "meh-rolling-eyes",
+  "memory",
+  "menorah",
+  "mercury",
+  "meteor",
+  "microchip",
+  "microphone",
+  "microphone-alt",
+  "microphone-alt-slash",
+  "microphone-slash",
+  "microscope",
+  "minus",
+  "minus-circle",
+  "minus-square",
+  "mitten",
+  "mobile",
+  "mobile-alt",
+  "money-bill",
+  "money-bill-alt",
+  "money-bill-wave",
+  "money-bill-wave-alt",
+  "money-check",
+  "money-check-alt",
+  "monument",
+  "moon",
+  "mortar-pestle",
+  "mosque",
+  "motorcycle",
+  "mountain",
+  "mouse",
+  "mouse-pointer",
+  "mug-hot",
+  "music",
+  "network-wired",
+  "neuter",
+  "newspaper",
+  "not-equal",
+  "notes-medical",
+  "object-group",
+  "object-ungroup",
+  "oil-can",
+  "om",
+  "otter",
+  "outdent",
+  "pager",
+  "paint-brush",
+  "paint-roller",
+  "palette",
+  "pallet",
+  "paper-plane",
+  "paperclip",
+  "parachute-box",
+  "paragraph",
+  "parking",
+  "passport",
+  "pastafarianism",
+  "paste",
+  "pause",
+  "pause-circle",
+  "paw",
+  "peace",
+  "pen",
+  "pen-alt",
+  "pen-fancy",
+  "pen-nib",
+  "pen-square",
+  "pencil-alt",
+  "pencil-ruler",
+  "people-carry",
+  "pepper-hot",
+  "percent",
+  "percentage",
+  "person-booth",
+  "phone",
+  "phone-alt",
+  "phone-slash",
+  "phone-square",
+  "phone-square-alt",
+  "phone-volume",
+  "photo-video",
+  "piggy-bank",
+  "pills",
+  "pizza-slice",
+  "place-of-worship",
+  "plane",
+  "plane-arrival",
+  "plane-departure",
+  "play",
+  "play-circle",
+  "plug",
+  "plus",
+  "plus-circle",
+  "plus-square",
+  "podcast",
+  "poll",
+  "poll-h",
+  "poo",
+  "poo-storm",
+  "poop",
+  "portrait",
+  "pound-sign",
+  "power-off",
+  "pray",
+  "praying-hands",
+  "prescription",
+  "prescription-bottle",
+  "prescription-bottle-alt",
+  "print",
+  "procedures",
+  "project-diagram",
+  "puzzle-piece",
+  "qrcode",
+  "question",
+  "question-circle",
+  "quidditch",
+  "quote-left",
+  "quote-right",
+  "quran",
+  "radiation",
+  "radiation-alt",
+  "rainbow",
+  "random",
+  "receipt",
+  "record-vinyl",
+  "recycle",
+  "redo",
+  "redo-alt",
+  "registered",
+  "remove-format",
+  "reply",
+  "reply-all",
+  "republican",
+  "restroom",
+  "retweet",
+  "ribbon",
+  "ring",
+  "road",
+  "robot",
+  "rocket",
+  "route",
+  "rss",
+  "rss-square",
+  "ruble-sign",
+  "ruler",
+  "ruler-combined",
+  "ruler-horizontal",
+  "ruler-vertical",
+  "running",
+  "rupee-sign",
+  "sad-cry",
+  "sad-tear",
+  "satellite",
+  "satellite-dish",
+  "save",
+  "school",
+  "screwdriver",
+  "scroll",
+  "sd-card",
+  "search",
+  "search-dollar",
+  "search-location",
+  "search-minus",
+  "search-plus",
+  "seedling",
+  "server",
+  "shapes",
+  "share",
+  "share-alt",
+  "share-alt-square",
+  "share-square",
+  "shekel-sign",
+  "shield-alt",
+  "ship",
+  "shipping-fast",
+  "shoe-prints",
+  "shopping-bag",
+  "shopping-basket",
+  "shopping-cart",
+  "shower",
+  "shuttle-van",
+  "sign",
+  "sign-in-alt",
+  "sign-language",
+  "sign-out-alt",
+  "signal",
+  "signature",
+  "sim-card",
+  "sitemap",
+  "skating",
+  "skiing",
+  "skiing-nordic",
+  "skull",
+  "skull-crossbones",
+  "slash",
+  "sleigh",
+  "sliders-h",
+  "smile",
+  "smile-beam",
+  "smile-wink",
+  "smog",
+  "smoking",
+  "smoking-ban",
+  "sms",
+  "snowboarding",
+  "snowflake",
+  "snowman",
+  "snowplow",
+  "socks",
+  "solar-panel",
+  "sort",
+  "sort-alpha-down",
+  "sort-alpha-down-alt",
+  "sort-alpha-up",
+  "sort-alpha-up-alt",
+  "sort-amount-down",
+  "sort-amount-down-alt",
+  "sort-amount-up",
+  "sort-amount-up-alt",
+  "sort-down",
+  "sort-numeric-down",
+  "sort-numeric-down-alt",
+  "sort-numeric-up",
+  "sort-numeric-up-alt",
+  "sort-up",
+  "spa",
+  "space-shuttle",
+  "spell-check",
+  "spider",
+  "spinner",
+  "splotch",
+  "spray-can",
+  "square",
+  "square-full",
+  "square-root-alt",
+  "stamp",
+  "star",
+  "star-and-crescent",
+  "star-half",
+  "star-half-alt",
+  "star-of-david",
+  "star-of-life",
+  "step-backward",
+  "step-forward",
+  "stethoscope",
+  "sticky-note",
+  "stop",
+  "stop-circle",
+  "stopwatch",
+  "store",
+  "store-alt",
+  "stream",
+  "street-view",
+  "strikethrough",
+  "stroopwafel",
+  "subscript",
+  "subway",
+  "suitcase",
+  "suitcase-rolling",
+  "sun",
+  "superscript",
+  "surprise",
+  "swatchbook",
+  "swimmer",
+  "swimming-pool",
+  "synagogue",
+  "sync",
+  "sync-alt",
+  "syringe",
+  "table",
+  "table-tennis",
+  "tablet",
+  "tablet-alt",
+  "tablets",
+  "tachometer-alt",
+  "tag",
+  "tags",
+  "tape",
+  "tasks",
+  "taxi",
+  "teeth",
+  "teeth-open",
+  "temperature-high",
+  "temperature-low",
+  "tenge",
+  "terminal",
+  "text-height",
+  "text-width",
+  "th",
+  "th-large",
+  "th-list",
+  "theater-masks",
+  "thermometer",
+  "thermometer-empty",
+  "thermometer-full",
+  "thermometer-half",
+  "thermometer-quarter",
+  "thermometer-three-quarters",
+  "thumbs-down",
+  "thumbs-up",
+  "thumbtack",
+  "ticket-alt",
+  "times",
+  "times-circle",
+  "tint",
+  "tint-slash",
+  "tired",
+  "toggle-off",
+  "toggle-on",
+  "toilet",
+  "toilet-paper",
+  "toolbox",
+  "tools",
+  "tooth",
+  "torah",
+  "torii-gate",
+  "tractor",
+  "trademark",
+  "traffic-light",
+  "trailer",
+  "train",
+  "tram",
+  "transgender",
+  "transgender-alt",
+  "trash",
+  "trash-alt",
+  "trash-restore",
+  "trash-restore-alt",
+  "tree",
+  "trophy",
+  "truck",
+  "truck-loading",
+  "truck-monster",
+  "truck-moving",
+  "truck-pickup",
+  "tshirt",
+  "tty",
+  "tv",
+  "umbrella",
+  "umbrella-beach",
+  "underline",
+  "undo",
+  "undo-alt",
+  "universal-access",
+  "university",
+  "unlink",
+  "unlock",
+  "unlock-alt",
+  "upload",
+  "user",
+  "user-alt",
+  "user-alt-slash",
+  "user-astronaut",
+  "user-check",
+  "user-circle",
+  "user-clock",
+  "user-cog",
+  "user-edit",
+  "user-friends",
+  "user-graduate",
+  "user-injured",
+  "user-lock",
+  "user-md",
+  "user-minus",
+  "user-ninja",
+  "user-nurse",
+  "user-plus",
+  "user-secret",
+  "user-shield",
+  "user-slash",
+  "user-tag",
+  "user-tie",
+  "user-times",
+  "users",
+  "users-cog",
+  "utensil-spoon",
+  "utensils",
+  "vector-square",
+  "venus",
+  "venus-double",
+  "venus-mars",
+  "vial",
+  "vials",
+  "video",
+  "video-slash",
+  "vihara",
+  "voicemail",
+  "volleyball-ball",
+  "volume-down",
+  "volume-mute",
+  "volume-off",
+  "volume-up",
+  "vote-yea",
+  "vr-cardboard",
+  "walking",
+  "wallet",
+  "warehouse",
+  "water",
+  "wave-square",
+  "weight",
+  "weight-hanging",
+  "wheelchair",
+  "wifi",
+  "wind",
+  "window-close",
+  "window-maximize",
+  "window-minimize",
+  "window-restore",
+  "wine-bottle",
+  "wine-glass",
+  "wine-glass-alt",
+  "won-sign",
+  "wrench",
+  "x-ray",
+  "yen-sign",
+  "yin-yang",
+];
+module.exports = [
+  {
+    url: "/icon/getList",
+    type: "post",
+    response(config) {
+      const { title, pageNo = 1, pageSize = 72 } = config.body;
+      let mockList = data.filter((item) => {
+        if (title && item.indexOf(title) < 0) return false;
+        return true;
+      });
+      const pageList = mockList.filter(
+        (item, index) =>
+          index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
+      );
+      return {
+        code: 200,
+        msg: "success",
+        totalCount: mockList.length,
+        data: pageList,
+      };
+    },
+  },
+];

+ 51 - 0
mock/controller/menuManagement.js

@@ -0,0 +1,51 @@
+module.exports = [
+  {
+    url: "/menuManagement/getTree",
+    type: "post",
+    response(config) {
+      return {
+        code: 200,
+        msg: "success",
+        totalCount: 999,
+        data: [
+          {
+            id: "root",
+            label: "全部角色",
+            children: [
+              {
+                id: "@id",
+                permission: "admin",
+                label: "admin角色",
+              },
+              {
+                id: "@id",
+                permission: "editor",
+                label: "editor角色",
+              },
+            ],
+          },
+        ],
+      };
+    },
+  },
+  {
+    url: "/menuManagement/doEdit",
+    type: "post",
+    response(config) {
+      return {
+        code: 200,
+        msg: "模拟保存成功",
+      };
+    },
+  },
+  {
+    url: "/menuManagement/doDelete",
+    type: "post",
+    response(config) {
+      return {
+        code: 200,
+        msg: "模拟删除成功",
+      };
+    },
+  },
+];

+ 38 - 0
mock/controller/notice.js

@@ -0,0 +1,38 @@
+const data = [
+  {
+    title: "究竟是什么样的终点,才配得上这一路的颠沛流离。。。",
+    closable: false,
+    type: "success",
+  },
+  {
+    title:
+      "作者寄语:感谢Star,感恩相遇,愿世间美好与我们环环相扣,加油!屏幕前的我们,打破桎梏,坚守初心。其实人生改变命运的机会并没有太多,我们并不是不优秀,我们也并不是一无是处,我们也希望驻足山巅被众人仰望,也许我们缺少的只是一个机会,缺少的只是生命中的导师,我希望这个框架帮助到更多的人,希望有一天,我们面试的时候不再胆怯,希望有一天别人看到的不仅仅是你的努力,还有你的功成名就,出人头地。",
+    closable: false,
+    type: "warning",
+  },
+  {
+    title:
+      "鸣谢:尤雨溪、蒋豪群、element-ui、唐金州、花裤衩、贤心、iView、uView的开源项目给我带来的很多的灵感,弱小的人才习惯嘲讽与否定,内心强大的人从不吝啬赞美与鼓励,人生在世,得到每个人的认可几乎是痴心妄想,我也只是一条略懂前端的咸鱼,可我仍一直怀揣着改变世界的梦想,希望我们每个人,不管过程怎样,结局都是美好的。",
+    closable: false,
+    type: "success",
+  },
+  {
+    title:
+      "随笔:我一直在寻找开源的真谛,我一直再想什么是开源,我一开始觉得免费就是开源,好像又不是。我理解的开源是:你也开源,我也开源,大家一起贡献,相互帮助。我最担心的事情是:我一个小人物,去伺候一众的伸手党,我想,这不是开源该有的氛围。我还太年轻,不懂什么是格局,我只知道,无私的帮助他人,能给我带来快乐,却不能给我带来收入,当然,有时候,快乐对我来说就已经足够了。可惜我是一个人,没有精力帮助到每一个人,可惜这个世界需要赚钱,才能过上平凡的生活,可惜了我的梦想,这个物欲横流的时代,理想主义的我们,即使内心坚决如铁,也似乎寸步难行。",
+    closable: false,
+    type: "success",
+  },
+];
+module.exports = [
+  {
+    url: "/notice/getList",
+    type: "post",
+    response() {
+      return {
+        code: 200,
+        msg: "success",
+        data,
+      };
+    },
+  },
+];

+ 42 - 0
mock/controller/personalCenter.js

@@ -0,0 +1,42 @@
+const { mock } = require("mockjs");
+
+module.exports = [
+  {
+    url: "/personalCenter/getList",
+    type: "post",
+    response(config) {
+      return {
+        code: 200,
+        msg: "success",
+        totalCount: 999,
+        data: mock({
+          "data|10": [
+            {
+              id: "@id",
+            },
+          ],
+        }).data,
+      };
+    },
+  },
+  {
+    url: "/personalCenter/doEdit",
+    type: "post",
+    response(config) {
+      return {
+        code: 200,
+        msg: "模拟保存成功",
+      };
+    },
+  },
+  {
+    url: "/personalCenter/doDelete",
+    type: "post",
+    response(config) {
+      return {
+        code: 200,
+        msg: "模拟删除成功",
+      };
+    },
+  },
+];

+ 2296 - 0
mock/controller/remixIcon.js

@@ -0,0 +1,2296 @@
+const data = [
+  "24-hours-fill",
+  "24-hours-line",
+  "4k-fill",
+  "4k-line",
+  "a-b",
+  "account-box-fill",
+  "account-box-line",
+  "account-circle-fill",
+  "account-circle-line",
+  "account-pin-box-fill",
+  "account-pin-box-line",
+  "account-pin-circle-fill",
+  "account-pin-circle-line",
+  "add-box-fill",
+  "add-box-line",
+  "add-circle-fill",
+  "add-circle-line",
+  "add-fill",
+  "add-line",
+  "admin-fill",
+  "admin-line",
+  "advertisement-fill",
+  "advertisement-line",
+  "airplay-fill",
+  "airplay-line",
+  "alarm-fill",
+  "alarm-line",
+  "alarm-warning-fill",
+  "alarm-warning-line",
+  "album-fill",
+  "album-line",
+  "alert-fill",
+  "alert-line",
+  "aliens-fill",
+  "aliens-line",
+  "align-bottom",
+  "align-center",
+  "align-justify",
+  "align-left",
+  "align-right",
+  "align-top",
+  "align-vertically",
+  "alipay-fill",
+  "alipay-line",
+  "amazon-fill",
+  "amazon-line",
+  "anchor-fill",
+  "anchor-line",
+  "ancient-gate-fill",
+  "ancient-gate-line",
+  "ancient-pavilion-fill",
+  "ancient-pavilion-line",
+  "android-fill",
+  "android-line",
+  "angularjs-fill",
+  "angularjs-line",
+  "anticlockwise-2-fill",
+  "anticlockwise-2-line",
+  "anticlockwise-fill",
+  "anticlockwise-line",
+  "app-store-fill",
+  "app-store-line",
+  "apple-fill",
+  "apple-line",
+  "apps-2-fill",
+  "apps-2-line",
+  "apps-fill",
+  "apps-line",
+  "archive-drawer-fill",
+  "archive-drawer-line",
+  "archive-fill",
+  "archive-line",
+  "arrow-down-circle-fill",
+  "arrow-down-circle-line",
+  "arrow-down-fill",
+  "arrow-down-line",
+  "arrow-down-s-fill",
+  "arrow-down-s-line",
+  "arrow-drop-down-fill",
+  "arrow-drop-down-line",
+  "arrow-drop-left-fill",
+  "arrow-drop-left-line",
+  "arrow-drop-right-fill",
+  "arrow-drop-right-line",
+  "arrow-drop-up-fill",
+  "arrow-drop-up-line",
+  "arrow-go-back-fill",
+  "arrow-go-back-line",
+  "arrow-go-forward-fill",
+  "arrow-go-forward-line",
+  "arrow-left-circle-fill",
+  "arrow-left-circle-line",
+  "arrow-left-down-fill",
+  "arrow-left-down-line",
+  "arrow-left-fill",
+  "arrow-left-line",
+  "arrow-left-right-fill",
+  "arrow-left-right-line",
+  "arrow-left-s-fill",
+  "arrow-left-s-line",
+  "arrow-left-up-fill",
+  "arrow-left-up-line",
+  "arrow-right-circle-fill",
+  "arrow-right-circle-line",
+  "arrow-right-down-fill",
+  "arrow-right-down-line",
+  "arrow-right-fill",
+  "arrow-right-line",
+  "arrow-right-s-fill",
+  "arrow-right-s-line",
+  "arrow-right-up-fill",
+  "arrow-right-up-line",
+  "arrow-up-circle-fill",
+  "arrow-up-circle-line",
+  "arrow-up-down-fill",
+  "arrow-up-down-line",
+  "arrow-up-fill",
+  "arrow-up-line",
+  "arrow-up-s-fill",
+  "arrow-up-s-line",
+  "artboard-2-fill",
+  "artboard-2-line",
+  "artboard-fill",
+  "artboard-line",
+  "article-fill",
+  "article-line",
+  "aspect-ratio-fill",
+  "aspect-ratio-line",
+  "asterisk",
+  "at-fill",
+  "at-line",
+  "attachment-2",
+  "attachment-fill",
+  "attachment-line",
+  "auction-fill",
+  "auction-line",
+  "award-fill",
+  "award-line",
+  "baidu-fill",
+  "baidu-line",
+  "ball-pen-fill",
+  "ball-pen-line",
+  "bank-card-2-fill",
+  "bank-card-2-line",
+  "bank-card-fill",
+  "bank-card-line",
+  "bank-fill",
+  "bank-line",
+  "bar-chart-2-fill",
+  "bar-chart-2-line",
+  "bar-chart-box-fill",
+  "bar-chart-box-line",
+  "bar-chart-fill",
+  "bar-chart-grouped-fill",
+  "bar-chart-grouped-line",
+  "bar-chart-horizontal-fill",
+  "bar-chart-horizontal-line",
+  "bar-chart-line",
+  "barcode-box-fill",
+  "barcode-box-line",
+  "barcode-fill",
+  "barcode-line",
+  "barricade-fill",
+  "barricade-line",
+  "base-station-fill",
+  "base-station-line",
+  "basketball-fill",
+  "basketball-line",
+  "battery-2-charge-fill",
+  "battery-2-charge-line",
+  "battery-2-fill",
+  "battery-2-line",
+  "battery-charge-fill",
+  "battery-charge-line",
+  "battery-fill",
+  "battery-line",
+  "battery-low-fill",
+  "battery-low-line",
+  "battery-saver-fill",
+  "battery-saver-line",
+  "battery-share-fill",
+  "battery-share-line",
+  "bear-smile-fill",
+  "bear-smile-line",
+  "behance-fill",
+  "behance-line",
+  "bell-fill",
+  "bell-line",
+  "bike-fill",
+  "bike-line",
+  "bilibili-fill",
+  "bilibili-line",
+  "bill-fill",
+  "bill-line",
+  "billiards-fill",
+  "billiards-line",
+  "bit-coin-fill",
+  "bit-coin-line",
+  "blaze-fill",
+  "blaze-line",
+  "bluetooth-connect-fill",
+  "bluetooth-connect-line",
+  "bluetooth-fill",
+  "bluetooth-line",
+  "blur-off-fill",
+  "blur-off-line",
+  "body-scan-fill",
+  "body-scan-line",
+  "bold",
+  "book-2-fill",
+  "book-2-line",
+  "book-3-fill",
+  "book-3-line",
+  "book-fill",
+  "book-line",
+  "book-mark-fill",
+  "book-mark-line",
+  "book-open-fill",
+  "book-open-line",
+  "book-read-fill",
+  "book-read-line",
+  "booklet-fill",
+  "booklet-line",
+  "bookmark-2-fill",
+  "bookmark-2-line",
+  "bookmark-3-fill",
+  "bookmark-3-line",
+  "bookmark-fill",
+  "bookmark-line",
+  "boxing-fill",
+  "boxing-line",
+  "braces-fill",
+  "braces-line",
+  "brackets-fill",
+  "brackets-line",
+  "briefcase-2-fill",
+  "briefcase-2-line",
+  "briefcase-3-fill",
+  "briefcase-3-line",
+  "briefcase-4-fill",
+  "briefcase-4-line",
+  "briefcase-5-fill",
+  "briefcase-5-line",
+  "briefcase-fill",
+  "briefcase-line",
+  "bring-forward",
+  "bring-to-front",
+  "broadcast-fill",
+  "broadcast-line",
+  "brush-2-fill",
+  "brush-2-line",
+  "brush-3-fill",
+  "brush-3-line",
+  "brush-4-fill",
+  "brush-4-line",
+  "brush-fill",
+  "brush-line",
+  "bubble-chart-fill",
+  "bubble-chart-line",
+  "bug-2-fill",
+  "bug-2-line",
+  "bug-fill",
+  "bug-line",
+  "building-2-fill",
+  "building-2-line",
+  "building-3-fill",
+  "building-3-line",
+  "building-4-fill",
+  "building-4-line",
+  "building-fill",
+  "building-line",
+  "bus-2-fill",
+  "bus-2-line",
+  "bus-fill",
+  "bus-line",
+  "bus-wifi-fill",
+  "bus-wifi-line",
+  "cactus-fill",
+  "cactus-line",
+  "cake-2-fill",
+  "cake-2-line",
+  "cake-3-fill",
+  "cake-3-line",
+  "cake-fill",
+  "cake-line",
+  "calculator-fill",
+  "calculator-line",
+  "calendar-2-fill",
+  "calendar-2-line",
+  "calendar-check-fill",
+  "calendar-check-line",
+  "calendar-event-fill",
+  "calendar-event-line",
+  "calendar-fill",
+  "calendar-line",
+  "calendar-todo-fill",
+  "calendar-todo-line",
+  "camera-2-fill",
+  "camera-2-line",
+  "camera-3-fill",
+  "camera-3-line",
+  "camera-fill",
+  "camera-lens-fill",
+  "camera-lens-line",
+  "camera-line",
+  "camera-off-fill",
+  "camera-off-line",
+  "camera-switch-fill",
+  "camera-switch-line",
+  "capsule-fill",
+  "capsule-line",
+  "car-fill",
+  "car-line",
+  "car-washing-fill",
+  "car-washing-line",
+  "caravan-fill",
+  "caravan-line",
+  "cast-fill",
+  "cast-line",
+  "cellphone-fill",
+  "cellphone-line",
+  "celsius-fill",
+  "celsius-line",
+  "centos-fill",
+  "centos-line",
+  "character-recognition-fill",
+  "character-recognition-line",
+  "charging-pile-2-fill",
+  "charging-pile-2-line",
+  "charging-pile-fill",
+  "charging-pile-line",
+  "chat-1-fill",
+  "chat-1-line",
+  "chat-2-fill",
+  "chat-2-line",
+  "chat-3-fill",
+  "chat-3-line",
+  "chat-4-fill",
+  "chat-4-line",
+  "chat-check-fill",
+  "chat-check-line",
+  "chat-delete-fill",
+  "chat-delete-line",
+  "chat-download-fill",
+  "chat-download-line",
+  "chat-follow-up-fill",
+  "chat-follow-up-line",
+  "chat-forward-fill",
+  "chat-forward-line",
+  "chat-heart-fill",
+  "chat-heart-line",
+  "chat-history-fill",
+  "chat-history-line",
+  "chat-new-fill",
+  "chat-new-line",
+  "chat-off-fill",
+  "chat-off-line",
+  "chat-poll-fill",
+  "chat-poll-line",
+  "chat-private-fill",
+  "chat-private-line",
+  "chat-quote-fill",
+  "chat-quote-line",
+  "chat-settings-fill",
+  "chat-settings-line",
+  "chat-smile-2-fill",
+  "chat-smile-2-line",
+  "chat-smile-3-fill",
+  "chat-smile-3-line",
+  "chat-smile-fill",
+  "chat-smile-line",
+  "chat-upload-fill",
+  "chat-upload-line",
+  "chat-voice-fill",
+  "chat-voice-line",
+  "check-double-fill",
+  "check-double-line",
+  "check-fill",
+  "check-line",
+  "checkbox-blank-circle-fill",
+  "checkbox-blank-circle-line",
+  "checkbox-blank-fill",
+  "checkbox-blank-line",
+  "checkbox-circle-fill",
+  "checkbox-circle-line",
+  "checkbox-fill",
+  "checkbox-indeterminate-fill",
+  "checkbox-indeterminate-line",
+  "checkbox-line",
+  "checkbox-multiple-blank-fill",
+  "checkbox-multiple-blank-line",
+  "checkbox-multiple-fill",
+  "checkbox-multiple-line",
+  "china-railway-fill",
+  "china-railway-line",
+  "chrome-fill",
+  "chrome-line",
+  "clapperboard-fill",
+  "clapperboard-line",
+  "clipboard-fill",
+  "clipboard-line",
+  "clockwise-2-fill",
+  "clockwise-2-line",
+  "clockwise-fill",
+  "clockwise-line",
+  "close-circle-fill",
+  "close-circle-line",
+  "close-fill",
+  "close-line",
+  "closed-captioning-fill",
+  "closed-captioning-line",
+  "cloud-fill",
+  "cloud-line",
+  "cloud-off-fill",
+  "cloud-off-line",
+  "cloud-windy-fill",
+  "cloud-windy-line",
+  "cloudy-2-fill",
+  "cloudy-2-line",
+  "cloudy-fill",
+  "cloudy-line",
+  "code-box-fill",
+  "code-box-line",
+  "code-fill",
+  "code-line",
+  "code-s-fill",
+  "code-s-line",
+  "code-s-slash-fill",
+  "code-s-slash-line",
+  "code-view",
+  "codepen-fill",
+  "codepen-line",
+  "coin-fill",
+  "coin-line",
+  "coins-fill",
+  "coins-line",
+  "collage-fill",
+  "collage-line",
+  "command-fill",
+  "command-line",
+  "community-fill",
+  "community-line",
+  "compass-2-fill",
+  "compass-2-line",
+  "compass-3-fill",
+  "compass-3-line",
+  "compass-4-fill",
+  "compass-4-line",
+  "compass-discover-fill",
+  "compass-discover-line",
+  "compass-fill",
+  "compass-line",
+  "compasses-2-fill",
+  "compasses-2-line",
+  "compasses-fill",
+  "compasses-line",
+  "computer-fill",
+  "computer-line",
+  "contacts-book-2-fill",
+  "contacts-book-2-line",
+  "contacts-book-fill",
+  "contacts-book-line",
+  "contacts-book-upload-fill",
+  "contacts-book-upload-line",
+  "contacts-fill",
+  "contacts-line",
+  "contrast-2-fill",
+  "contrast-2-line",
+  "contrast-drop-2-fill",
+  "contrast-drop-2-line",
+  "contrast-drop-fill",
+  "contrast-drop-line",
+  "contrast-fill",
+  "contrast-line",
+  "copper-coin-fill",
+  "copper-coin-line",
+  "copper-diamond-fill",
+  "copper-diamond-line",
+  "copyleft-fill",
+  "copyleft-line",
+  "copyright-fill",
+  "copyright-line",
+  "coreos-fill",
+  "coreos-line",
+  "coupon-2-fill",
+  "coupon-2-line",
+  "coupon-3-fill",
+  "coupon-3-line",
+  "coupon-4-fill",
+  "coupon-4-line",
+  "coupon-5-fill",
+  "coupon-5-line",
+  "coupon-fill",
+  "coupon-line",
+  "cpu-fill",
+  "cpu-line",
+  "creative-commons-by-fill",
+  "creative-commons-by-line",
+  "creative-commons-fill",
+  "creative-commons-line",
+  "creative-commons-nc-fill",
+  "creative-commons-nc-line",
+  "creative-commons-nd-fill",
+  "creative-commons-nd-line",
+  "creative-commons-sa-fill",
+  "creative-commons-sa-line",
+  "creative-commons-zero-fill",
+  "creative-commons-zero-line",
+  "criminal-fill",
+  "criminal-line",
+  "crop-2-fill",
+  "crop-2-line",
+  "crop-fill",
+  "crop-line",
+  "css3-fill",
+  "css3-line",
+  "cup-fill",
+  "cup-line",
+  "currency-fill",
+  "currency-line",
+  "cursor-fill",
+  "cursor-line",
+  "customer-service-2-fill",
+  "customer-service-2-line",
+  "customer-service-fill",
+  "customer-service-line",
+  "dashboard-2-fill",
+  "dashboard-2-line",
+  "dashboard-3-fill",
+  "dashboard-3-line",
+  "dashboard-fill",
+  "dashboard-line",
+  "database-2-fill",
+  "database-2-line",
+  "database-fill",
+  "database-line",
+  "delete-back-2-fill",
+  "delete-back-2-line",
+  "delete-back-fill",
+  "delete-back-line",
+  "delete-bin-2-fill",
+  "delete-bin-2-line",
+  "delete-bin-3-fill",
+  "delete-bin-3-line",
+  "delete-bin-4-fill",
+  "delete-bin-4-line",
+  "delete-bin-5-fill",
+  "delete-bin-5-line",
+  "delete-bin-6-fill",
+  "delete-bin-6-line",
+  "delete-bin-7-fill",
+  "delete-bin-7-line",
+  "delete-bin-fill",
+  "delete-bin-line",
+  "delete-column",
+  "delete-row",
+  "device-fill",
+  "device-line",
+  "device-recover-fill",
+  "device-recover-line",
+  "dingding-fill",
+  "dingding-line",
+  "direction-fill",
+  "direction-line",
+  "disc-fill",
+  "disc-line",
+  "discord-fill",
+  "discord-line",
+  "discuss-fill",
+  "discuss-line",
+  "dislike-fill",
+  "dislike-line",
+  "disqus-fill",
+  "disqus-line",
+  "divide-fill",
+  "divide-line",
+  "donut-chart-fill",
+  "donut-chart-line",
+  "door-closed-fill",
+  "door-closed-line",
+  "door-fill",
+  "door-line",
+  "door-lock-box-fill",
+  "door-lock-box-line",
+  "door-lock-fill",
+  "door-lock-line",
+  "door-open-fill",
+  "door-open-line",
+  "dossier-fill",
+  "dossier-line",
+  "douban-fill",
+  "douban-line",
+  "double-quotes-l",
+  "double-quotes-r",
+  "download-2-fill",
+  "download-2-line",
+  "download-cloud-2-fill",
+  "download-cloud-2-line",
+  "download-cloud-fill",
+  "download-cloud-line",
+  "download-fill",
+  "download-line",
+  "draft-fill",
+  "draft-line",
+  "drag-drop-fill",
+  "drag-drop-line",
+  "drag-move-2-fill",
+  "drag-move-2-line",
+  "drag-move-fill",
+  "drag-move-line",
+  "dribbble-fill",
+  "dribbble-line",
+  "drive-fill",
+  "drive-line",
+  "drizzle-fill",
+  "drizzle-line",
+  "drop-fill",
+  "drop-line",
+  "dropbox-fill",
+  "dropbox-line",
+  "dual-sim-1-fill",
+  "dual-sim-1-line",
+  "dual-sim-2-fill",
+  "dual-sim-2-line",
+  "dv-fill",
+  "dv-line",
+  "dvd-fill",
+  "dvd-line",
+  "e-bike-2-fill",
+  "e-bike-2-line",
+  "e-bike-fill",
+  "e-bike-line",
+  "earth-fill",
+  "earth-line",
+  "earthquake-fill",
+  "earthquake-line",
+  "edge-fill",
+  "edge-line",
+  "edit-2-fill",
+  "edit-2-line",
+  "edit-box-fill",
+  "edit-box-line",
+  "edit-circle-fill",
+  "edit-circle-line",
+  "edit-fill",
+  "edit-line",
+  "eject-fill",
+  "eject-line",
+  "emotion-2-fill",
+  "emotion-2-line",
+  "emotion-fill",
+  "emotion-happy-fill",
+  "emotion-happy-line",
+  "emotion-laugh-fill",
+  "emotion-laugh-line",
+  "emotion-line",
+  "emotion-normal-fill",
+  "emotion-normal-line",
+  "emotion-sad-fill",
+  "emotion-sad-line",
+  "emotion-unhappy-fill",
+  "emotion-unhappy-line",
+  "empathize-fill",
+  "empathize-line",
+  "emphasis-cn",
+  "emphasis",
+  "english-input",
+  "equalizer-fill",
+  "equalizer-line",
+  "eraser-fill",
+  "eraser-line",
+  "error-warning-fill",
+  "error-warning-line",
+  "evernote-fill",
+  "evernote-line",
+  "exchange-box-fill",
+  "exchange-box-line",
+  "exchange-cny-fill",
+  "exchange-cny-line",
+  "exchange-dollar-fill",
+  "exchange-dollar-line",
+  "exchange-fill",
+  "exchange-funds-fill",
+  "exchange-funds-line",
+  "exchange-line",
+  "external-link-fill",
+  "external-link-line",
+  "eye-2-fill",
+  "eye-2-line",
+  "eye-close-fill",
+  "eye-close-line",
+  "eye-fill",
+  "eye-line",
+  "eye-off-fill",
+  "eye-off-line",
+  "facebook-box-fill",
+  "facebook-box-line",
+  "facebook-circle-fill",
+  "facebook-circle-line",
+  "facebook-fill",
+  "facebook-line",
+  "fahrenheit-fill",
+  "fahrenheit-line",
+  "feedback-fill",
+  "feedback-line",
+  "file-2-fill",
+  "file-2-line",
+  "file-3-fill",
+  "file-3-line",
+  "file-4-fill",
+  "file-4-line",
+  "file-add-fill",
+  "file-add-line",
+  "file-chart-2-fill",
+  "file-chart-2-line",
+  "file-chart-fill",
+  "file-chart-line",
+  "file-cloud-fill",
+  "file-cloud-line",
+  "file-code-fill",
+  "file-code-line",
+  "file-copy-2-fill",
+  "file-copy-2-line",
+  "file-copy-fill",
+  "file-copy-line",
+  "file-damage-fill",
+  "file-damage-line",
+  "file-download-fill",
+  "file-download-line",
+  "file-edit-fill",
+  "file-edit-line",
+  "file-excel-2-fill",
+  "file-excel-2-line",
+  "file-excel-fill",
+  "file-excel-line",
+  "file-fill",
+  "file-forbid-fill",
+  "file-forbid-line",
+  "file-gif-fill",
+  "file-gif-line",
+  "file-history-fill",
+  "file-history-line",
+  "file-hwp-fill",
+  "file-hwp-line",
+  "file-info-fill",
+  "file-info-line",
+  "file-line",
+  "file-list-2-fill",
+  "file-list-2-line",
+  "file-list-3-fill",
+  "file-list-3-line",
+  "file-list-fill",
+  "file-list-line",
+  "file-lock-fill",
+  "file-lock-line",
+  "file-mark-fill",
+  "file-mark-line",
+  "file-music-fill",
+  "file-music-line",
+  "file-paper-2-fill",
+  "file-paper-2-line",
+  "file-paper-fill",
+  "file-paper-line",
+  "file-pdf-fill",
+  "file-pdf-line",
+  "file-ppt-2-fill",
+  "file-ppt-2-line",
+  "file-ppt-fill",
+  "file-ppt-line",
+  "file-reduce-fill",
+  "file-reduce-line",
+  "file-search-fill",
+  "file-search-line",
+  "file-settings-fill",
+  "file-settings-line",
+  "file-shield-2-fill",
+  "file-shield-2-line",
+  "file-shield-fill",
+  "file-shield-line",
+  "file-shred-fill",
+  "file-shred-line",
+  "file-text-fill",
+  "file-text-line",
+  "file-transfer-fill",
+  "file-transfer-line",
+  "file-unknow-fill",
+  "file-unknow-line",
+  "file-upload-fill",
+  "file-upload-line",
+  "file-user-fill",
+  "file-user-line",
+  "file-warning-fill",
+  "file-warning-line",
+  "file-word-2-fill",
+  "file-word-2-line",
+  "file-word-fill",
+  "file-word-line",
+  "file-zip-fill",
+  "file-zip-line",
+  "film-fill",
+  "film-line",
+  "filter-2-fill",
+  "filter-2-line",
+  "filter-3-fill",
+  "filter-3-line",
+  "filter-fill",
+  "filter-line",
+  "filter-off-fill",
+  "filter-off-line",
+  "find-replace-fill",
+  "find-replace-line",
+  "finder-fill",
+  "finder-line",
+  "fingerprint-2-fill",
+  "fingerprint-2-line",
+  "fingerprint-fill",
+  "fingerprint-line",
+  "fire-fill",
+  "fire-line",
+  "firefox-fill",
+  "firefox-line",
+  "first-aid-kit-fill",
+  "first-aid-kit-line",
+  "flag-2-fill",
+  "flag-2-line",
+  "flag-fill",
+  "flag-line",
+  "flashlight-fill",
+  "flashlight-line",
+  "flask-fill",
+  "flask-line",
+  "flight-land-fill",
+  "flight-land-line",
+  "flight-takeoff-fill",
+  "flight-takeoff-line",
+  "flood-fill",
+  "flood-line",
+  "flow-chart",
+  "flutter-fill",
+  "flutter-line",
+  "focus-2-fill",
+  "focus-2-line",
+  "focus-3-fill",
+  "focus-3-line",
+  "focus-fill",
+  "focus-line",
+  "foggy-fill",
+  "foggy-line",
+  "folder-2-fill",
+  "folder-2-line",
+  "folder-3-fill",
+  "folder-3-line",
+  "folder-4-fill",
+  "folder-4-line",
+  "folder-5-fill",
+  "folder-5-line",
+  "folder-add-fill",
+  "folder-add-line",
+  "folder-chart-2-fill",
+  "folder-chart-2-line",
+  "folder-chart-fill",
+  "folder-chart-line",
+  "folder-download-fill",
+  "folder-download-line",
+  "folder-fill",
+  "folder-forbid-fill",
+  "folder-forbid-line",
+  "folder-history-fill",
+  "folder-history-line",
+  "folder-info-fill",
+  "folder-info-line",
+  "folder-keyhole-fill",
+  "folder-keyhole-line",
+  "folder-line",
+  "folder-lock-fill",
+  "folder-lock-line",
+  "folder-music-fill",
+  "folder-music-line",
+  "folder-open-fill",
+  "folder-open-line",
+  "folder-received-fill",
+  "folder-received-line",
+  "folder-reduce-fill",
+  "folder-reduce-line",
+  "folder-settings-fill",
+  "folder-settings-line",
+  "folder-shared-fill",
+  "folder-shared-line",
+  "folder-shield-2-fill",
+  "folder-shield-2-line",
+  "folder-shield-fill",
+  "folder-shield-line",
+  "folder-transfer-fill",
+  "folder-transfer-line",
+  "folder-unknow-fill",
+  "folder-unknow-line",
+  "folder-upload-fill",
+  "folder-upload-line",
+  "folder-user-fill",
+  "folder-user-line",
+  "folder-warning-fill",
+  "folder-warning-line",
+  "folder-zip-fill",
+  "folder-zip-line",
+  "folders-fill",
+  "folders-line",
+  "font-color",
+  "font-size-2",
+  "font-size",
+  "football-fill",
+  "football-line",
+  "footprint-fill",
+  "footprint-line",
+  "forbid-2-fill",
+  "forbid-2-line",
+  "forbid-fill",
+  "forbid-line",
+  "format-clear",
+  "fridge-fill",
+  "fridge-line",
+  "fullscreen-exit-fill",
+  "fullscreen-exit-line",
+  "fullscreen-fill",
+  "fullscreen-line",
+  "function-fill",
+  "function-line",
+  "functions",
+  "funds-box-fill",
+  "funds-box-line",
+  "funds-fill",
+  "funds-line",
+  "gallery-fill",
+  "gallery-line",
+  "gallery-upload-fill",
+  "gallery-upload-line",
+  "game-fill",
+  "game-line",
+  "gamepad-fill",
+  "gamepad-line",
+  "gas-station-fill",
+  "gas-station-line",
+  "gatsby-fill",
+  "gatsby-line",
+  "genderless-fill",
+  "genderless-line",
+  "ghost-2-fill",
+  "ghost-2-line",
+  "ghost-fill",
+  "ghost-line",
+  "ghost-smile-fill",
+  "ghost-smile-line",
+  "gift-2-fill",
+  "gift-2-line",
+  "gift-fill",
+  "gift-line",
+  "git-branch-fill",
+  "git-branch-line",
+  "git-commit-fill",
+  "git-commit-line",
+  "git-merge-fill",
+  "git-merge-line",
+  "git-pull-request-fill",
+  "git-pull-request-line",
+  "git-repository-commits-fill",
+  "git-repository-commits-line",
+  "git-repository-fill",
+  "git-repository-line",
+  "git-repository-private-fill",
+  "git-repository-private-line",
+  "github-fill",
+  "github-line",
+  "gitlab-fill",
+  "gitlab-line",
+  "global-fill",
+  "global-line",
+  "globe-fill",
+  "globe-line",
+  "goblet-fill",
+  "goblet-line",
+  "google-fill",
+  "google-line",
+  "google-play-fill",
+  "google-play-line",
+  "government-fill",
+  "government-line",
+  "gps-fill",
+  "gps-line",
+  "gradienter-fill",
+  "gradienter-line",
+  "grid-fill",
+  "grid-line",
+  "group-2-fill",
+  "group-2-line",
+  "group-fill",
+  "group-line",
+  "guide-fill",
+  "guide-line",
+  "h-1",
+  "h-2",
+  "h-3",
+  "h-4",
+  "h-5",
+  "h-6",
+  "hail-fill",
+  "hail-line",
+  "hammer-fill",
+  "hammer-line",
+  "hand-coin-fill",
+  "hand-coin-line",
+  "hand-heart-fill",
+  "hand-heart-line",
+  "hand-sanitizer-fill",
+  "hand-sanitizer-line",
+  "handbag-fill",
+  "handbag-line",
+  "hard-drive-2-fill",
+  "hard-drive-2-line",
+  "hard-drive-fill",
+  "hard-drive-line",
+  "hashtag",
+  "haze-2-fill",
+  "haze-2-line",
+  "haze-fill",
+  "haze-line",
+  "hd-fill",
+  "hd-line",
+  "heading",
+  "headphone-fill",
+  "headphone-line",
+  "health-book-fill",
+  "health-book-line",
+  "heart-2-fill",
+  "heart-2-line",
+  "heart-3-fill",
+  "heart-3-line",
+  "heart-add-fill",
+  "heart-add-line",
+  "heart-fill",
+  "heart-line",
+  "heart-pulse-fill",
+  "heart-pulse-line",
+  "hearts-fill",
+  "hearts-line",
+  "heavy-showers-fill",
+  "heavy-showers-line",
+  "history-fill",
+  "history-line",
+  "home-2-fill",
+  "home-2-line",
+  "home-3-fill",
+  "home-3-line",
+  "home-4-fill",
+  "home-4-line",
+  "home-5-fill",
+  "home-5-line",
+  "home-6-fill",
+  "home-6-line",
+  "home-7-fill",
+  "home-7-line",
+  "home-8-fill",
+  "home-8-line",
+  "home-fill",
+  "home-gear-fill",
+  "home-gear-line",
+  "home-heart-fill",
+  "home-heart-line",
+  "home-line",
+  "home-smile-2-fill",
+  "home-smile-2-line",
+  "home-smile-fill",
+  "home-smile-line",
+  "home-wifi-fill",
+  "home-wifi-line",
+  "honor-of-kings-fill",
+  "honor-of-kings-line",
+  "honour-fill",
+  "honour-line",
+  "hospital-fill",
+  "hospital-line",
+  "hotel-bed-fill",
+  "hotel-bed-line",
+  "hotel-fill",
+  "hotel-line",
+  "hotspot-fill",
+  "hotspot-line",
+  "hq-fill",
+  "hq-line",
+  "html5-fill",
+  "html5-line",
+  "ie-fill",
+  "ie-line",
+  "image-2-fill",
+  "image-2-line",
+  "image-add-fill",
+  "image-add-line",
+  "image-edit-fill",
+  "image-edit-line",
+  "image-fill",
+  "image-line",
+  "inbox-archive-fill",
+  "inbox-archive-line",
+  "inbox-fill",
+  "inbox-line",
+  "inbox-unarchive-fill",
+  "inbox-unarchive-line",
+  "increase-decrease-fill",
+  "increase-decrease-line",
+  "indent-decrease",
+  "indent-increase",
+  "indeterminate-circle-fill",
+  "indeterminate-circle-line",
+  "information-fill",
+  "information-line",
+  "infrared-thermometer-fill",
+  "infrared-thermometer-line",
+  "ink-bottle-fill",
+  "ink-bottle-line",
+  "input-cursor-move",
+  "input-method-fill",
+  "input-method-line",
+  "insert-column-left",
+  "insert-column-right",
+  "insert-row-bottom",
+  "insert-row-top",
+  "instagram-fill",
+  "instagram-line",
+  "install-fill",
+  "install-line",
+  "invision-fill",
+  "invision-line",
+  "italic",
+  "kakao-talk-fill",
+  "kakao-talk-line",
+  "key-2-fill",
+  "key-2-line",
+  "key-fill",
+  "key-line",
+  "keyboard-box-fill",
+  "keyboard-box-line",
+  "keyboard-fill",
+  "keyboard-line",
+  "keynote-fill",
+  "keynote-line",
+  "knife-blood-fill",
+  "knife-blood-line",
+  "knife-fill",
+  "knife-line",
+  "landscape-fill",
+  "landscape-line",
+  "layout-2-fill",
+  "layout-2-line",
+  "layout-3-fill",
+  "layout-3-line",
+  "layout-4-fill",
+  "layout-4-line",
+  "layout-5-fill",
+  "layout-5-line",
+  "layout-6-fill",
+  "layout-6-line",
+  "layout-bottom-2-fill",
+  "layout-bottom-2-line",
+  "layout-bottom-fill",
+  "layout-bottom-line",
+  "layout-column-fill",
+  "layout-column-line",
+  "layout-fill",
+  "layout-grid-fill",
+  "layout-grid-line",
+  "layout-left-2-fill",
+  "layout-left-2-line",
+  "layout-left-fill",
+  "layout-left-line",
+  "layout-line",
+  "layout-masonry-fill",
+  "layout-masonry-line",
+  "layout-right-2-fill",
+  "layout-right-2-line",
+  "layout-right-fill",
+  "layout-right-line",
+  "layout-row-fill",
+  "layout-row-line",
+  "layout-top-2-fill",
+  "layout-top-2-line",
+  "layout-top-fill",
+  "layout-top-line",
+  "leaf-fill",
+  "leaf-line",
+  "lifebuoy-fill",
+  "lifebuoy-line",
+  "lightbulb-fill",
+  "lightbulb-flash-fill",
+  "lightbulb-flash-line",
+  "lightbulb-line",
+  "line-chart-fill",
+  "line-chart-line",
+  "line-fill",
+  "line-height",
+  "line-line",
+  "link-m",
+  "link-unlink-m",
+  "link-unlink",
+  "link",
+  "linkedin-box-fill",
+  "linkedin-box-line",
+  "linkedin-fill",
+  "linkedin-line",
+  "links-fill",
+  "links-line",
+  "list-check-2",
+  "list-check",
+  "list-ordered",
+  "list-settings-fill",
+  "list-settings-line",
+  "list-unordered",
+  "live-fill",
+  "live-line",
+  "loader-2-fill",
+  "loader-2-line",
+  "loader-3-fill",
+  "loader-3-line",
+  "loader-4-fill",
+  "loader-4-line",
+  "loader-5-fill",
+  "loader-5-line",
+  "loader-fill",
+  "loader-line",
+  "lock-2-fill",
+  "lock-2-line",
+  "lock-fill",
+  "lock-line",
+  "lock-password-fill",
+  "lock-password-line",
+  "lock-unlock-fill",
+  "lock-unlock-line",
+  "login-box-fill",
+  "login-box-line",
+  "login-circle-fill",
+  "login-circle-line",
+  "logout-box-fill",
+  "logout-box-line",
+  "logout-box-r-fill",
+  "logout-box-r-line",
+  "logout-circle-fill",
+  "logout-circle-line",
+  "logout-circle-r-fill",
+  "logout-circle-r-line",
+  "luggage-cart-fill",
+  "luggage-cart-line",
+  "luggage-deposit-fill",
+  "luggage-deposit-line",
+  "lungs-fill",
+  "lungs-line",
+  "mac-fill",
+  "mac-line",
+  "macbook-fill",
+  "macbook-line",
+  "magic-fill",
+  "magic-line",
+  "mail-add-fill",
+  "mail-add-line",
+  "mail-check-fill",
+  "mail-check-line",
+  "mail-close-fill",
+  "mail-close-line",
+  "mail-download-fill",
+  "mail-download-line",
+  "mail-fill",
+  "mail-forbid-fill",
+  "mail-forbid-line",
+  "mail-line",
+  "mail-lock-fill",
+  "mail-lock-line",
+  "mail-open-fill",
+  "mail-open-line",
+  "mail-send-fill",
+  "mail-send-line",
+  "mail-settings-fill",
+  "mail-settings-line",
+  "mail-star-fill",
+  "mail-star-line",
+  "mail-unread-fill",
+  "mail-unread-line",
+  "mail-volume-fill",
+  "mail-volume-line",
+  "map-2-fill",
+  "map-2-line",
+  "map-fill",
+  "map-line",
+  "map-pin-2-fill",
+  "map-pin-2-line",
+  "map-pin-3-fill",
+  "map-pin-3-line",
+  "map-pin-4-fill",
+  "map-pin-4-line",
+  "map-pin-5-fill",
+  "map-pin-5-line",
+  "map-pin-add-fill",
+  "map-pin-add-line",
+  "map-pin-fill",
+  "map-pin-line",
+  "map-pin-range-fill",
+  "map-pin-range-line",
+  "map-pin-time-fill",
+  "map-pin-time-line",
+  "map-pin-user-fill",
+  "map-pin-user-line",
+  "mark-pen-fill",
+  "mark-pen-line",
+  "markdown-fill",
+  "markdown-line",
+  "markup-fill",
+  "markup-line",
+  "mastercard-fill",
+  "mastercard-line",
+  "mastodon-fill",
+  "mastodon-line",
+  "medal-2-fill",
+  "medal-2-line",
+  "medal-fill",
+  "medal-line",
+  "medicine-bottle-fill",
+  "medicine-bottle-line",
+  "medium-fill",
+  "medium-line",
+  "men-fill",
+  "men-line",
+  "mental-health-fill",
+  "mental-health-line",
+  "menu-2-fill",
+  "menu-2-line",
+  "menu-3-fill",
+  "menu-3-line",
+  "menu-4-fill",
+  "menu-4-line",
+  "menu-5-fill",
+  "menu-5-line",
+  "menu-add-fill",
+  "menu-add-line",
+  "menu-fill",
+  "menu-fold-fill",
+  "menu-fold-line",
+  "menu-line",
+  "menu-unfold-fill",
+  "menu-unfold-line",
+  "merge-cells-horizontal",
+  "merge-cells-vertical",
+  "message-2-fill",
+  "message-2-line",
+  "message-3-fill",
+  "message-3-line",
+  "message-fill",
+  "message-line",
+  "messenger-fill",
+  "messenger-line",
+  "meteor-fill",
+  "meteor-line",
+  "mic-2-fill",
+  "mic-2-line",
+  "mic-fill",
+  "mic-line",
+  "mic-off-fill",
+  "mic-off-line",
+  "mickey-fill",
+  "mickey-line",
+  "microscope-fill",
+  "microscope-line",
+  "microsoft-fill",
+  "microsoft-line",
+  "mind-map",
+  "mini-program-fill",
+  "mini-program-line",
+  "mist-fill",
+  "mist-line",
+  "money-cny-box-fill",
+  "money-cny-box-line",
+  "money-cny-circle-fill",
+  "money-cny-circle-line",
+  "money-dollar-box-fill",
+  "money-dollar-box-line",
+  "money-dollar-circle-fill",
+  "money-dollar-circle-line",
+  "money-euro-box-fill",
+  "money-euro-box-line",
+  "money-euro-circle-fill",
+  "money-euro-circle-line",
+  "money-pound-box-fill",
+  "money-pound-box-line",
+  "money-pound-circle-fill",
+  "money-pound-circle-line",
+  "moon-clear-fill",
+  "moon-clear-line",
+  "moon-cloudy-fill",
+  "moon-cloudy-line",
+  "moon-fill",
+  "moon-foggy-fill",
+  "moon-foggy-line",
+  "moon-line",
+  "more-2-fill",
+  "more-2-line",
+  "more-fill",
+  "more-line",
+  "motorbike-fill",
+  "motorbike-line",
+  "mouse-fill",
+  "mouse-line",
+  "movie-2-fill",
+  "movie-2-line",
+  "movie-fill",
+  "movie-line",
+  "music-2-fill",
+  "music-2-line",
+  "music-fill",
+  "music-line",
+  "mv-fill",
+  "mv-line",
+  "navigation-fill",
+  "navigation-line",
+  "netease-cloud-music-fill",
+  "netease-cloud-music-line",
+  "netflix-fill",
+  "netflix-line",
+  "newspaper-fill",
+  "newspaper-line",
+  "node-tree",
+  "notification-2-fill",
+  "notification-2-line",
+  "notification-3-fill",
+  "notification-3-line",
+  "notification-4-fill",
+  "notification-4-line",
+  "notification-badge-fill",
+  "notification-badge-line",
+  "notification-fill",
+  "notification-line",
+  "notification-off-fill",
+  "notification-off-line",
+  "npmjs-fill",
+  "npmjs-line",
+  "number-0",
+  "number-1",
+  "number-2",
+  "number-3",
+  "number-4",
+  "number-5",
+  "number-6",
+  "number-7",
+  "number-8",
+  "number-9",
+  "numbers-fill",
+  "numbers-line",
+  "nurse-fill",
+  "nurse-line",
+  "oil-fill",
+  "oil-line",
+  "omega",
+  "open-arm-fill",
+  "open-arm-line",
+  "open-source-fill",
+  "open-source-line",
+  "opera-fill",
+  "opera-line",
+  "order-play-fill",
+  "order-play-line",
+  "organization-chart",
+  "outlet-2-fill",
+  "outlet-2-line",
+  "outlet-fill",
+  "outlet-line",
+  "page-separator",
+  "pages-fill",
+  "pages-line",
+  "paint-brush-fill",
+  "paint-brush-line",
+  "paint-fill",
+  "paint-line",
+  "palette-fill",
+  "palette-line",
+  "pantone-fill",
+  "pantone-line",
+  "paragraph",
+  "parent-fill",
+  "parent-line",
+  "parentheses-fill",
+  "parentheses-line",
+  "parking-box-fill",
+  "parking-box-line",
+  "parking-fill",
+  "parking-line",
+  "passport-fill",
+  "passport-line",
+  "patreon-fill",
+  "patreon-line",
+  "pause-circle-fill",
+  "pause-circle-line",
+  "pause-fill",
+  "pause-line",
+  "pause-mini-fill",
+  "pause-mini-line",
+  "paypal-fill",
+  "paypal-line",
+  "pen-nib-fill",
+  "pen-nib-line",
+  "pencil-fill",
+  "pencil-line",
+  "pencil-ruler-2-fill",
+  "pencil-ruler-2-line",
+  "pencil-ruler-fill",
+  "pencil-ruler-line",
+  "percent-fill",
+  "percent-line",
+  "phone-camera-fill",
+  "phone-camera-line",
+  "phone-fill",
+  "phone-find-fill",
+  "phone-find-line",
+  "phone-line",
+  "phone-lock-fill",
+  "phone-lock-line",
+  "picture-in-picture-2-fill",
+  "picture-in-picture-2-line",
+  "picture-in-picture-exit-fill",
+  "picture-in-picture-exit-line",
+  "picture-in-picture-fill",
+  "picture-in-picture-line",
+  "pie-chart-2-fill",
+  "pie-chart-2-line",
+  "pie-chart-box-fill",
+  "pie-chart-box-line",
+  "pie-chart-fill",
+  "pie-chart-line",
+  "pin-distance-fill",
+  "pin-distance-line",
+  "ping-pong-fill",
+  "ping-pong-line",
+  "pinterest-fill",
+  "pinterest-line",
+  "pinyin-input",
+  "pixelfed-fill",
+  "pixelfed-line",
+  "plane-fill",
+  "plane-line",
+  "plant-fill",
+  "plant-line",
+  "play-circle-fill",
+  "play-circle-line",
+  "play-fill",
+  "play-line",
+  "play-list-2-fill",
+  "play-list-2-line",
+  "play-list-add-fill",
+  "play-list-add-line",
+  "play-list-fill",
+  "play-list-line",
+  "play-mini-fill",
+  "play-mini-line",
+  "playstation-fill",
+  "playstation-line",
+  "plug-2-fill",
+  "plug-2-line",
+  "plug-fill",
+  "plug-line",
+  "polaroid-2-fill",
+  "polaroid-2-line",
+  "polaroid-fill",
+  "polaroid-line",
+  "police-car-fill",
+  "police-car-line",
+  "price-tag-2-fill",
+  "price-tag-2-line",
+  "price-tag-3-fill",
+  "price-tag-3-line",
+  "price-tag-fill",
+  "price-tag-line",
+  "printer-cloud-fill",
+  "printer-cloud-line",
+  "printer-fill",
+  "printer-line",
+  "product-hunt-fill",
+  "product-hunt-line",
+  "profile-fill",
+  "profile-line",
+  "projector-2-fill",
+  "projector-2-line",
+  "projector-fill",
+  "projector-line",
+  "psychotherapy-fill",
+  "psychotherapy-line",
+  "pulse-fill",
+  "pulse-line",
+  "pushpin-2-fill",
+  "pushpin-2-line",
+  "pushpin-fill",
+  "pushpin-line",
+  "qq-fill",
+  "qq-line",
+  "qr-code-fill",
+  "qr-code-line",
+  "qr-scan-2-fill",
+  "qr-scan-2-line",
+  "qr-scan-fill",
+  "qr-scan-line",
+  "question-answer-fill",
+  "question-answer-line",
+  "question-fill",
+  "question-line",
+  "question-mark",
+  "questionnaire-fill",
+  "questionnaire-line",
+  "quill-pen-fill",
+  "quill-pen-line",
+  "radar-fill",
+  "radar-line",
+  "radio-2-fill",
+  "radio-2-line",
+  "radio-button-fill",
+  "radio-button-line",
+  "radio-fill",
+  "radio-line",
+  "rainbow-fill",
+  "rainbow-line",
+  "rainy-fill",
+  "rainy-line",
+  "reactjs-fill",
+  "reactjs-line",
+  "record-circle-fill",
+  "record-circle-line",
+  "record-mail-fill",
+  "record-mail-line",
+  "recycle-fill",
+  "recycle-line",
+  "red-packet-fill",
+  "red-packet-line",
+  "reddit-fill",
+  "reddit-line",
+  "refresh-fill",
+  "refresh-line",
+  "refund-2-fill",
+  "refund-2-line",
+  "refund-fill",
+  "refund-line",
+  "registered-fill",
+  "registered-line",
+  "remixicon-fill",
+  "remixicon-line",
+  "remote-control-2-fill",
+  "remote-control-2-line",
+  "remote-control-fill",
+  "remote-control-line",
+  "repeat-2-fill",
+  "repeat-2-line",
+  "repeat-fill",
+  "repeat-line",
+  "repeat-one-fill",
+  "repeat-one-line",
+  "reply-all-fill",
+  "reply-all-line",
+  "reply-fill",
+  "reply-line",
+  "reserved-fill",
+  "reserved-line",
+  "rest-time-fill",
+  "rest-time-line",
+  "restart-fill",
+  "restart-line",
+  "restaurant-2-fill",
+  "restaurant-2-line",
+  "restaurant-fill",
+  "restaurant-line",
+  "rewind-fill",
+  "rewind-line",
+  "rewind-mini-fill",
+  "rewind-mini-line",
+  "rhythm-fill",
+  "rhythm-line",
+  "riding-fill",
+  "riding-line",
+  "road-map-fill",
+  "road-map-line",
+  "roadster-fill",
+  "roadster-line",
+  "robot-fill",
+  "robot-line",
+  "rocket-2-fill",
+  "rocket-2-line",
+  "rocket-fill",
+  "rocket-line",
+  "rotate-lock-fill",
+  "rotate-lock-line",
+  "rounded-corner",
+  "route-fill",
+  "route-line",
+  "router-fill",
+  "router-line",
+  "rss-fill",
+  "rss-line",
+  "ruler-2-fill",
+  "ruler-2-line",
+  "ruler-fill",
+  "ruler-line",
+  "run-fill",
+  "run-line",
+  "safari-fill",
+  "safari-line",
+  "safe-2-fill",
+  "safe-2-line",
+  "safe-fill",
+  "safe-line",
+  "sailboat-fill",
+  "sailboat-line",
+  "save-2-fill",
+  "save-2-line",
+  "save-3-fill",
+  "save-3-line",
+  "save-fill",
+  "save-line",
+  "scales-2-fill",
+  "scales-2-line",
+  "scales-3-fill",
+  "scales-3-line",
+  "scales-fill",
+  "scales-line",
+  "scan-2-fill",
+  "scan-2-line",
+  "scan-fill",
+  "scan-line",
+  "scissors-2-fill",
+  "scissors-2-line",
+  "scissors-cut-fill",
+  "scissors-cut-line",
+  "scissors-fill",
+  "scissors-line",
+  "screenshot-2-fill",
+  "screenshot-2-line",
+  "screenshot-fill",
+  "screenshot-line",
+  "sd-card-fill",
+  "sd-card-line",
+  "sd-card-mini-fill",
+  "sd-card-mini-line",
+  "search-2-fill",
+  "search-2-line",
+  "search-eye-fill",
+  "search-eye-line",
+  "search-fill",
+  "search-line",
+  "secure-payment-fill",
+  "secure-payment-line",
+  "seedling-fill",
+  "seedling-line",
+  "send-backward",
+  "send-plane-2-fill",
+  "send-plane-2-line",
+  "send-plane-fill",
+  "send-plane-line",
+  "send-to-back",
+  "sensor-fill",
+  "sensor-line",
+  "separator",
+  "server-fill",
+  "server-line",
+  "service-fill",
+  "service-line",
+  "settings-2-fill",
+  "settings-2-line",
+  "settings-3-fill",
+  "settings-3-line",
+  "settings-4-fill",
+  "settings-4-line",
+  "settings-5-fill",
+  "settings-5-line",
+  "settings-6-fill",
+  "settings-6-line",
+  "settings-fill",
+  "settings-line",
+  "shape-2-fill",
+  "shape-2-line",
+  "shape-fill",
+  "shape-line",
+  "share-box-fill",
+  "share-box-line",
+  "share-circle-fill",
+  "share-circle-line",
+  "share-fill",
+  "share-forward-2-fill",
+  "share-forward-2-line",
+  "share-forward-box-fill",
+  "share-forward-box-line",
+  "share-forward-fill",
+  "share-forward-line",
+  "share-line",
+  "shield-check-fill",
+  "shield-check-line",
+  "shield-cross-fill",
+  "shield-cross-line",
+  "shield-fill",
+  "shield-flash-fill",
+  "shield-flash-line",
+  "shield-keyhole-fill",
+  "shield-keyhole-line",
+  "shield-line",
+  "shield-star-fill",
+  "shield-star-line",
+  "shield-user-fill",
+  "shield-user-line",
+  "ship-2-fill",
+  "ship-2-line",
+  "ship-fill",
+  "ship-line",
+  "shirt-fill",
+  "shirt-line",
+  "shopping-bag-2-fill",
+  "shopping-bag-2-line",
+  "shopping-bag-3-fill",
+  "shopping-bag-3-line",
+  "shopping-bag-fill",
+  "shopping-bag-line",
+  "shopping-basket-2-fill",
+  "shopping-basket-2-line",
+  "shopping-basket-fill",
+  "shopping-basket-line",
+  "shopping-cart-2-fill",
+  "shopping-cart-2-line",
+  "shopping-cart-fill",
+  "shopping-cart-line",
+  "showers-fill",
+  "showers-line",
+  "shuffle-fill",
+  "shuffle-line",
+  "shut-down-fill",
+  "shut-down-line",
+  "side-bar-fill",
+  "side-bar-line",
+  "signal-tower-fill",
+  "signal-tower-line",
+  "signal-wifi-1-fill",
+  "signal-wifi-1-line",
+  "signal-wifi-2-fill",
+  "signal-wifi-2-line",
+  "signal-wifi-3-fill",
+  "signal-wifi-3-line",
+  "signal-wifi-error-fill",
+  "signal-wifi-error-line",
+  "signal-wifi-fill",
+  "signal-wifi-line",
+  "signal-wifi-off-fill",
+  "signal-wifi-off-line",
+  "sim-card-2-fill",
+  "sim-card-2-line",
+  "sim-card-fill",
+  "sim-card-line",
+  "single-quotes-l",
+  "single-quotes-r",
+  "sip-fill",
+  "sip-line",
+  "skip-back-fill",
+  "skip-back-line",
+  "skip-back-mini-fill",
+  "skip-back-mini-line",
+  "skip-forward-fill",
+  "skip-forward-line",
+  "skip-forward-mini-fill",
+  "skip-forward-mini-line",
+  "skull-2-fill",
+  "skull-2-line",
+  "skull-fill",
+  "skull-line",
+  "skype-fill",
+  "skype-line",
+  "slack-fill",
+  "slack-line",
+  "slice-fill",
+  "slice-line",
+  "slideshow-2-fill",
+  "slideshow-2-line",
+  "slideshow-3-fill",
+  "slideshow-3-line",
+  "slideshow-4-fill",
+  "slideshow-4-line",
+  "slideshow-fill",
+  "slideshow-line",
+  "smartphone-fill",
+  "smartphone-line",
+  "snapchat-fill",
+  "snapchat-line",
+  "snowy-fill",
+  "snowy-line",
+  "sort-asc",
+  "sort-desc",
+  "sound-module-fill",
+  "sound-module-line",
+  "soundcloud-fill",
+  "soundcloud-line",
+  "space-ship-fill",
+  "space-ship-line",
+  "space",
+  "spam-2-fill",
+  "spam-2-line",
+  "spam-3-fill",
+  "spam-3-line",
+  "spam-fill",
+  "spam-line",
+  "speaker-2-fill",
+  "speaker-2-line",
+  "speaker-3-fill",
+  "speaker-3-line",
+  "speaker-fill",
+  "speaker-line",
+  "spectrum-fill",
+  "spectrum-line",
+  "speed-fill",
+  "speed-line",
+  "speed-mini-fill",
+  "speed-mini-line",
+  "split-cells-horizontal",
+  "split-cells-vertical",
+  "spotify-fill",
+  "spotify-line",
+  "spy-fill",
+  "spy-line",
+  "stack-fill",
+  "stack-line",
+  "stack-overflow-fill",
+  "stack-overflow-line",
+  "stackshare-fill",
+  "stackshare-line",
+  "star-fill",
+  "star-half-fill",
+  "star-half-line",
+  "star-half-s-fill",
+  "star-half-s-line",
+  "star-line",
+  "star-s-fill",
+  "star-s-line",
+  "star-smile-fill",
+  "star-smile-line",
+  "steam-fill",
+  "steam-line",
+  "steering-2-fill",
+  "steering-2-line",
+  "steering-fill",
+  "steering-line",
+  "stethoscope-fill",
+  "stethoscope-line",
+  "sticky-note-2-fill",
+  "sticky-note-2-line",
+  "sticky-note-fill",
+  "sticky-note-line",
+  "stock-fill",
+  "stock-line",
+  "stop-circle-fill",
+  "stop-circle-line",
+  "stop-fill",
+  "stop-line",
+  "stop-mini-fill",
+  "stop-mini-line",
+  "store-2-fill",
+  "store-2-line",
+  "store-3-fill",
+  "store-3-line",
+  "store-fill",
+  "store-line",
+  "strikethrough-2",
+  "strikethrough",
+  "subscript-2",
+  "subscript",
+  "subtract-fill",
+  "subtract-line",
+  "subway-fill",
+  "subway-line",
+  "subway-wifi-fill",
+  "subway-wifi-line",
+  "suitcase-2-fill",
+  "suitcase-2-line",
+  "suitcase-3-fill",
+  "suitcase-3-line",
+  "suitcase-fill",
+  "suitcase-line",
+  "sun-cloudy-fill",
+  "sun-cloudy-line",
+  "sun-fill",
+  "sun-foggy-fill",
+  "sun-foggy-line",
+  "sun-line",
+  "superscript-2",
+  "superscript",
+  "surgical-mask-fill",
+  "surgical-mask-line",
+  "surround-sound-fill",
+  "surround-sound-line",
+  "survey-fill",
+  "survey-line",
+  "swap-box-fill",
+  "swap-box-line",
+  "swap-fill",
+  "swap-line",
+  "switch-fill",
+  "switch-line",
+  "sword-fill",
+  "sword-line",
+  "syringe-fill",
+  "syringe-line",
+  "t-box-fill",
+  "t-box-line",
+  "t-shirt-2-fill",
+  "t-shirt-2-line",
+  "t-shirt-air-fill",
+  "t-shirt-air-line",
+  "t-shirt-fill",
+  "t-shirt-line",
+  "table-2",
+  "table-alt-fill",
+  "table-alt-line",
+  "table-fill",
+  "table-line",
+  "tablet-fill",
+  "tablet-line",
+  "takeaway-fill",
+  "takeaway-line",
+  "taobao-fill",
+  "taobao-line",
+  "tape-fill",
+  "tape-line",
+  "task-fill",
+  "task-line",
+  "taxi-fill",
+  "taxi-line",
+  "taxi-wifi-fill",
+  "taxi-wifi-line",
+  "team-fill",
+  "team-line",
+  "telegram-fill",
+  "telegram-line",
+  "temp-cold-fill",
+  "temp-cold-line",
+  "temp-hot-fill",
+  "temp-hot-line",
+  "terminal-box-fill",
+  "terminal-box-line",
+  "terminal-fill",
+  "terminal-line",
+  "terminal-window-fill",
+  "terminal-window-line",
+  "test-tube-fill",
+  "test-tube-line",
+  "text-direction-l",
+  "text-direction-r",
+  "text-spacing",
+  "text-wrap",
+  "text",
+  "thermometer-fill",
+  "thermometer-line",
+  "thumb-down-fill",
+  "thumb-down-line",
+  "thumb-up-fill",
+  "thumb-up-line",
+  "thunderstorms-fill",
+  "thunderstorms-line",
+  "ticket-2-fill",
+  "ticket-2-line",
+  "ticket-fill",
+  "ticket-line",
+  "time-fill",
+  "time-line",
+  "timer-2-fill",
+  "timer-2-line",
+  "timer-fill",
+  "timer-flash-fill",
+  "timer-flash-line",
+  "timer-line",
+  "todo-fill",
+  "todo-line",
+  "toggle-fill",
+  "toggle-line",
+  "tools-fill",
+  "tools-line",
+  "tornado-fill",
+  "tornado-line",
+  "trademark-fill",
+  "trademark-line",
+  "traffic-light-fill",
+  "traffic-light-line",
+  "train-fill",
+  "train-line",
+  "train-wifi-fill",
+  "train-wifi-line",
+  "translate-2",
+  "translate",
+  "travesti-fill",
+  "travesti-line",
+  "treasure-map-fill",
+  "treasure-map-line",
+  "trello-fill",
+  "trello-line",
+  "trophy-fill",
+  "trophy-line",
+  "truck-fill",
+  "truck-line",
+  "tumblr-fill",
+  "tumblr-line",
+  "tv-2-fill",
+  "tv-2-line",
+  "tv-fill",
+  "tv-line",
+  "twitch-fill",
+  "twitch-line",
+  "twitter-fill",
+  "twitter-line",
+  "typhoon-fill",
+  "typhoon-line",
+  "u-disk-fill",
+  "u-disk-line",
+  "ubuntu-fill",
+  "ubuntu-line",
+  "umbrella-fill",
+  "umbrella-line",
+  "underline",
+  "uninstall-fill",
+  "uninstall-line",
+  "unsplash-fill",
+  "unsplash-line",
+  "upload-2-fill",
+  "upload-2-line",
+  "upload-cloud-2-fill",
+  "upload-cloud-2-line",
+  "upload-cloud-fill",
+  "upload-cloud-line",
+  "upload-fill",
+  "upload-line",
+  "usb-fill",
+  "usb-line",
+  "user-2-fill",
+  "user-2-line",
+  "user-3-fill",
+  "user-3-line",
+  "user-4-fill",
+  "user-4-line",
+  "user-5-fill",
+  "user-5-line",
+  "user-6-fill",
+  "user-6-line",
+  "user-add-fill",
+  "user-add-line",
+  "user-fill",
+  "user-follow-fill",
+  "user-follow-line",
+  "user-heart-fill",
+  "user-heart-line",
+  "user-line",
+  "user-location-fill",
+  "user-location-line",
+  "user-received-2-fill",
+  "user-received-2-line",
+  "user-received-fill",
+  "user-received-line",
+  "user-search-fill",
+  "user-search-line",
+  "user-settings-fill",
+  "user-settings-line",
+  "user-shared-2-fill",
+  "user-shared-2-line",
+  "user-shared-fill",
+  "user-shared-line",
+  "user-smile-fill",
+  "user-smile-line",
+  "user-star-fill",
+  "user-star-line",
+  "user-unfollow-fill",
+  "user-unfollow-line",
+  "user-voice-fill",
+  "user-voice-line",
+  "video-add-fill",
+  "video-add-line",
+  "video-chat-fill",
+  "video-chat-line",
+  "video-download-fill",
+  "video-download-line",
+  "video-fill",
+  "video-line",
+  "video-upload-fill",
+  "video-upload-line",
+  "vidicon-2-fill",
+  "vidicon-2-line",
+  "vidicon-fill",
+  "vidicon-line",
+  "vimeo-fill",
+  "vimeo-line",
+  "vip-crown-2-fill",
+  "vip-crown-2-line",
+  "vip-crown-fill",
+  "vip-crown-line",
+  "vip-diamond-fill",
+  "vip-diamond-line",
+  "vip-fill",
+  "vip-line",
+  "virus-fill",
+  "virus-line",
+  "visa-fill",
+  "visa-line",
+  "voice-recognition-fill",
+  "voice-recognition-line",
+  "voiceprint-fill",
+  "voiceprint-line",
+  "volume-down-fill",
+  "volume-down-line",
+  "volume-mute-fill",
+  "volume-mute-line",
+  "volume-off-vibrate-fill",
+  "volume-off-vibrate-line",
+  "volume-up-fill",
+  "volume-up-line",
+  "volume-vibrate-fill",
+  "volume-vibrate-line",
+  "vuejs-fill",
+  "vuejs-line",
+  "walk-fill",
+  "walk-line",
+  "wallet-2-fill",
+  "wallet-2-line",
+  "wallet-3-fill",
+  "wallet-3-line",
+  "wallet-fill",
+  "wallet-line",
+  "water-flash-fill",
+  "water-flash-line",
+  "webcam-fill",
+  "webcam-line",
+  "wechat-2-fill",
+  "wechat-2-line",
+  "wechat-fill",
+  "wechat-line",
+  "wechat-pay-fill",
+  "wechat-pay-line",
+  "weibo-fill",
+  "weibo-line",
+  "whatsapp-fill",
+  "whatsapp-line",
+  "wheelchair-fill",
+  "wheelchair-line",
+  "wifi-fill",
+  "wifi-line",
+  "wifi-off-fill",
+  "wifi-off-line",
+  "window-2-fill",
+  "window-2-line",
+  "window-fill",
+  "window-line",
+  "windows-fill",
+  "windows-line",
+  "windy-fill",
+  "windy-line",
+  "wireless-charging-fill",
+  "wireless-charging-line",
+  "women-fill",
+  "women-line",
+  "wubi-input",
+  "xbox-fill",
+  "xbox-line",
+  "xing-fill",
+  "xing-line",
+  "youtube-fill",
+  "youtube-line",
+  "zcool-fill",
+  "zcool-line",
+  "zhihu-fill",
+  "zhihu-line",
+  "zoom-in-fill",
+  "zoom-in-line",
+  "zoom-out-fill",
+  "zoom-out-line",
+  "zzz-fill",
+  "zzz-line",
+];
+module.exports = [
+  {
+    url: "/remixIcon/getList",
+    type: "post",
+    response(config) {
+      const { title, pageNo = 1, pageSize = 72 } = config.body;
+      let mockList = data.filter((item) => {
+        if (title && item.indexOf(title) < 0) return false;
+        return true;
+      });
+      const pageList = mockList.filter(
+        (item, index) =>
+          index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
+      );
+      return {
+        code: 200,
+        msg: "success",
+        totalCount: mockList.length,
+        data: pageList,
+      };
+    },
+  },
+];

+ 53 - 0
mock/controller/roleManagement.js

@@ -0,0 +1,53 @@
+const totalCount = 2;
+const List = [
+  {
+    id: "@id",
+    permission: "admin",
+  },
+  {
+    id: "@id",
+    permission: "editor",
+  },
+];
+module.exports = [
+  {
+    url: "/roleManagement/getList",
+    type: "post",
+    response(config) {
+      const { title = "", pageNo = 1, pageSize = 20 } = config.body;
+      let mockList = List.filter((item) => {
+        return !(title && item.title.indexOf(title) < 0);
+      });
+      const pageList = mockList.filter(
+        (item, index) =>
+          index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
+      );
+      return {
+        code: 200,
+        msg: "success",
+        totalCount,
+        data: pageList,
+      };
+    },
+  },
+  {
+    url: "/roleManagement/doEdit",
+    type: "post",
+    response() {
+      return {
+        code: 200,
+        msg: "模拟保存成功",
+      };
+    },
+  },
+  {
+    url: "/roleManagement/doDelete",
+    type: "post",
+    response() {
+      return {
+        code: 200,
+        msg: "模拟删除成功",
+      };
+    },
+  },
+];

+ 390 - 0
mock/controller/router.js

@@ -0,0 +1,390 @@
+const data = [
+  {
+    path: "/",
+    component: "Layout",
+    redirect: "index",
+    children: [
+      {
+        path: "index",
+        name: "Index",
+        component: "views/index/index",
+        meta: {
+          title: "首页",
+          icon: "home",
+          affix: true,
+        },
+      },
+    ],
+  },
+  {
+    path: "/personalCenter",
+    component: "Layout",
+    hidden: true,
+    redirect: "personalCenter",
+    children: [
+      {
+        path: "personalCenter",
+        name: "PersonalCenter",
+        component: "views/personalCenter/index",
+        meta: {
+          title: "个人中心",
+        },
+      },
+    ],
+  },
+  {
+    path: "/personnelManagement",
+    component: "Layout",
+    redirect: "noRedirect",
+    name: "PersonnelManagement",
+    meta: { title: "人员", icon: "users-cog", permissions: ["admin"] },
+    children: [
+      {
+        path: "userManagement",
+        name: "UserManagement",
+        component: "views/modules/system/userManagement/index",
+        meta: { title: "用户管理" },
+      },
+      {
+        path: "roleManagement",
+        name: "RoleManagement",
+        component: "views/modules/system/roleManagement/index",
+        meta: { title: "角色管理" },
+      },
+      {
+        path: "menuManagement",
+        name: "MenuManagement",
+        component: "views/modules/system/menuManagement/index",
+        meta: { title: "菜单管理", badge: "New" },
+      },
+    ],
+  },
+  {
+    path: "/vab",
+    component: "Layout",
+    redirect: "noRedirect",
+    name: "Vab",
+    alwaysShow: true,
+    meta: { title: "组件", icon: "cloud" },
+    children: [
+      {
+        path: "permissions",
+        name: "Permission",
+        component: "views/vab/permissions/index",
+        meta: {
+          title: "权限控制",
+          permissions: ["admin", "editor"],
+          badge: "New",
+        },
+      },
+      {
+        path: "icon",
+        component: "EmptyLayout",
+        redirect: "noRedirect",
+        name: "Icon",
+        meta: {
+          title: "图标",
+          permissions: ["admin"],
+        },
+        children: [
+          {
+            path: "awesomeIcon",
+            name: "AwesomeIcon",
+            component: "views/vab/icon/index",
+            meta: { title: "常规图标" },
+          },
+          {
+            path: "remixIcon",
+            name: "RemixIcon",
+            component: "views/vab/icon/remixIcon",
+            meta: { title: "小清新图标" },
+          },
+          {
+            path: "colorfulIcon",
+            name: "ColorfulIcon",
+            component: "views/vab/icon/colorfulIcon",
+            meta: { title: "多彩图标" },
+          },
+        ],
+      },
+      {
+        path: "table",
+        component: "EmptyLayout",
+        redirect: "noRedirect",
+        name: "Table",
+        meta: {
+          title: "表格",
+          permissions: ["admin"],
+        },
+        children: [
+          {
+            path: "comprehensiveTable",
+            name: "ComprehensiveTable",
+            component: "views/vab/table/index",
+            meta: { title: "综合表格" },
+          },
+          {
+            path: "inlineEditTable",
+            name: "InlineEditTable",
+            component: "views/vab/table/inlineEditTable",
+            meta: { title: "行内编辑" },
+          },
+        ],
+      },
+      {
+        path: "map",
+        name: "Map",
+        component: "views/vab/map/index",
+        meta: { title: "地图", permissions: ["admin"], badge: "Pro" },
+      },
+      {
+        path: "webSocket",
+        name: "WebSocket",
+        component: "views/vab/webSocket/index",
+        meta: { title: "webSocket", permissions: ["admin"] },
+      },
+      {
+        path: "form",
+        name: "Form",
+        component: "views/vab/form/index",
+        meta: { title: "表单", permissions: ["admin"] },
+      },
+      {
+        path: "element",
+        name: "Element",
+        component: "views/vab/element/index",
+        meta: { title: "常用组件", permissions: ["admin"] },
+      },
+      {
+        path: "tree",
+        name: "Tree",
+        component: "views/vab/tree/index",
+        meta: { title: "树", permissions: ["admin"] },
+      },
+      {
+        path: "card",
+        name: "Card",
+        component: "views/vab/card/index",
+        meta: { title: "卡片", permissions: ["admin"] },
+      },
+
+      {
+        path: "betterScroll",
+        name: "BetterScroll",
+        component: "views/vab/betterScroll/index",
+        meta: {
+          title: "滚动侦测",
+          permissions: ["admin"],
+        },
+      },
+      {
+        path: "verify",
+        name: "Verify",
+        component: "views/vab/verify/index",
+        meta: { title: "验证码", permissions: ["admin"] },
+      },
+      {
+        path: "menu1",
+        component: "views/vab/nested/menu1/index",
+        name: "Menu1",
+        alwaysShow: true,
+        meta: {
+          title: "嵌套路由 1",
+          permissions: ["admin"],
+        },
+        children: [
+          {
+            path: "menu1-1",
+            name: "Menu1-1",
+            alwaysShow: true,
+            meta: { title: "嵌套路由 1-1" },
+            component: "views/vab/nested/menu1/menu1-1/index",
+
+            children: [
+              {
+                path: "menu1-1-1",
+                name: "Menu1-1-1",
+                meta: { title: "嵌套路由 1-1-1" },
+                component: "views/vab/nested/menu1/menu1-1/menu1-1-1/index",
+              },
+            ],
+          },
+        ],
+      },
+      {
+        path: "magnifier",
+        name: "Magnifier",
+        component: "views/vab/magnifier/index",
+        meta: { title: "放大镜", permissions: ["admin"] },
+      },
+      {
+        path: "echarts",
+        name: "Echarts",
+        component: "views/vab/echarts/index",
+        meta: { title: "图表", permissions: ["admin"] },
+      },
+
+      {
+        path: "loading",
+        name: "Loading",
+        component: "views/vab/loading/index",
+        meta: { title: "loading", permissions: ["admin"] },
+      },
+      {
+        path: "player",
+        name: "Player",
+        component: "views/vab/player/index",
+        meta: { title: "视频播放器", permissions: ["admin"] },
+      },
+      {
+        path: "markdownEditor",
+        name: "MarkdownEditor",
+        component: "views/vab/markdownEditor/index",
+        meta: { title: "markdown编辑器", permissions: ["admin"] },
+      },
+      {
+        path: "editor",
+        name: "Editor",
+        component: "views/vab/editor/index",
+        meta: { title: "富文本编辑器", permissions: ["admin"], badge: "New" },
+      },
+      {
+        path: "qrCode",
+        name: "QrCode",
+        component: "views/vab/qrCode/index",
+        meta: { title: "二维码", permissions: ["admin"] },
+      },
+      {
+        path: "backToTop",
+        name: "BackToTop",
+        component: "views/vab/backToTop/index",
+        meta: { title: "返回顶部", permissions: ["admin"] },
+      },
+      {
+        path: "lodash",
+        name: "Lodash",
+        component: "views/vab/lodash/index",
+        meta: { title: "lodash", permissions: ["admin"] },
+      },
+      {
+        path: "imgComparison",
+        name: "ImgComparison",
+        component: "views/vab/imgComparison/index",
+        meta: { title: "图像拖拽比对", permissions: ["admin"] },
+      },
+      {
+        path: "codeGenerator",
+        name: "CodeGenerator",
+        component: "views/vab/codeGenerator/index",
+        meta: { title: "代码生成机", permissions: ["admin"] },
+      },
+      {
+        path: "markdown",
+        name: "Markdown",
+        component: "views/vab/markdown/index",
+        meta: { title: "markdown阅读器", permissions: ["admin"] },
+      },
+      {
+        path: "smallComponents",
+        name: "SmallComponents",
+        component: "views/vab/smallComponents/index",
+        meta: { title: "小组件", permissions: ["admin"] },
+      },
+
+      {
+        path: "upload",
+        name: "Upload",
+        component: "views/vab/upload/index",
+        meta: { title: "上传", permissions: ["admin"] },
+      },
+      {
+        path: "sticky",
+        name: "Sticky",
+        component: "views/vab/sticky/index",
+        meta: { title: "sticky吸附", permissions: ["admin"] },
+      },
+      {
+        path: "log",
+        name: "Log",
+        component: "views/vab/errorLog/index",
+        meta: { title: "错误日志模拟", permissions: ["admin"] },
+      },
+      {
+        path: "more",
+        name: "More",
+        component: "views/vab/more/index",
+        meta: { title: "更多组件", permissions: ["admin"] },
+      },
+    ],
+  },
+  {
+    path: "/mall",
+    component: "Layout",
+    redirect: "noRedirect",
+    name: "Mall",
+    meta: {
+      title: "商城",
+      icon: "shopping-cart",
+      permissions: ["admin"],
+    },
+
+    children: [
+      {
+        path: "pay",
+        name: "Pay",
+        component: "views/mall/pay/index",
+        meta: {
+          title: "支付",
+          noKeepAlive: true,
+        },
+        children: null,
+      },
+      {
+        path: "goodsList",
+        name: "GoodsList",
+        component: "views/mall/goodsList/index",
+        meta: {
+          title: "商品列表",
+        },
+      },
+      {
+        path: "goodsDetail",
+        name: "GoodsDetail",
+        component: "views/mall/goodsDetail/index",
+        meta: {
+          title: "商品详情",
+        },
+      },
+    ],
+  },
+  {
+    path: "/error",
+    component: "EmptyLayout",
+    redirect: "noRedirect",
+    name: "Error",
+    meta: { title: "错误页", icon: "bug" },
+    children: [
+      {
+        path: "401",
+        name: "Error401",
+        component: "views/401",
+        meta: { title: "401" },
+      },
+      {
+        path: "404",
+        name: "Error404",
+        component: "views/404",
+        meta: { title: "404" },
+      },
+    ],
+  },
+];
+module.exports = [
+  {
+    url: "/menu/navigate",
+    type: "post",
+    response() {
+      return { code: 200, msg: "success", data: data };
+    },
+  },
+];

+ 88 - 0
mock/controller/table.js

@@ -0,0 +1,88 @@
+const { mock } = require("mockjs");
+const { handleRandomImage } = require("../utils");
+
+const List = [];
+const count = 999;
+for (let i = 0; i < count; i++) {
+  List.push(
+    mock({
+      uuid: "@uuid",
+      id: "@id",
+      title: "@csentence(1, 2)",
+      "status|1": ["published", "draft", "deleted"],
+      author: "@cname",
+      datetime: "@datetime",
+      pageViews: "@integer(300, 5000)",
+      img: handleRandomImage(200, 200),
+      smallImg: handleRandomImage(40, 40),
+      switch: "@boolean",
+      percent: "@integer(80,99)",
+    })
+  );
+}
+
+module.exports = [
+  {
+    url: "/table/getList",
+    type: "post",
+    response(config) {
+      if (!config.body) {
+        return {
+          code: 200,
+          msg: "success",
+          totalCount: count,
+          data: mock({
+            "data|50": [
+              {
+                id: "@id",
+                title: "@csentence(1, 2)",
+                "status|1": ["published", "draft", "deleted"],
+                author: "@cname",
+                datetime: "@datetime",
+                pageViews: "@integer(300, 5000)",
+                img: handleRandomImage(200, 200),
+                smallImg: handleRandomImage(40, 40),
+                switch: "@boolean",
+                percent: "@integer(80,99)",
+              },
+            ],
+          }).data,
+        };
+      }
+      const { title = "", pageNo = 1, pageSize = 20 } = config.body;
+      let mockList = List.filter((item) => {
+        return !(title && item.title.indexOf(title) < 0);
+      });
+      const pageList = mockList.filter(
+        (item, index) =>
+          index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
+      );
+      return {
+        code: 200,
+        msg: "success",
+        totalCount: count,
+        data: pageList,
+      };
+    },
+  },
+  {
+    url: "/table/doEdit",
+    type: "post",
+    response() {
+      return {
+        code: 200,
+        msg: "模拟保存成功",
+      };
+    },
+  },
+  {
+    url: "/table/doDelete",
+    type: "post",
+    response() {
+      return {
+        code: 200,
+        msg: "模拟删除成功",
+      };
+    },
+  },
+];

+ 54 - 0
mock/controller/tree.js

@@ -0,0 +1,54 @@
+const data = [
+  {
+    id: "1",
+    parentId: "0",
+    name: "vue-admin-beautiful科技有限公司",
+    title: "vue-admin-beautiful科技有限公司",
+    text: "vue-admin-beautiful科技有限公司",
+    value: "1",
+    rank: 1,
+    children: [
+      {
+        id: "32816b88ff72423f960e7d492a386131",
+        parentId: "1",
+        name: "1103工作室",
+        title: "1103工作室",
+        text: "1103工作室",
+        value: "32816b88ff72423f960e7d492a386131",
+        rank: 2,
+        children: [
+          {
+            id: "9e11afc35d55475fb0bd3164b9684cbe",
+            parentId: "32816b88ff72423f960e7d492a386131",
+            name: "前端牛逼plus小组",
+            title: "前端牛逼plus小组",
+            text: "前端牛逼plus小组",
+            value: "9e11afc35d55475fb0bd3164b9684cbe",
+            rank: 3,
+            children: [
+              {
+                id: "4cc1b04635e4444292526c5391699077",
+                parentId: "9e11afc35d55475fb0bd3164b9684cbe",
+                name: "组员chuzhixin",
+                title: "组员chuzhixin",
+                text: "组员chuzhixin",
+                value: "4cc1b04635e4444292526c5391699077",
+                rank: 4,
+                children: [],
+              },
+            ],
+          },
+        ],
+      },
+    ],
+  },
+];
+module.exports = [
+  {
+    url: "/tree/list",
+    type: "post",
+    response() {
+      return { code: 200, msg: "success", data };
+    },
+  },
+];

+ 14 - 0
mock/controller/upload.js

@@ -0,0 +1,14 @@
+const data = [];
+module.exports = [
+  {
+    url: "/upload",
+    type: "post",
+    response(config) {
+      return {
+        code: 200,
+        msg: "success",
+        data: data,
+      };
+    },
+  },
+];

+ 95 - 0
mock/controller/user.js

@@ -0,0 +1,95 @@
+const accessTokens = {
+  admin: "admin-accessToken",
+  editor: "editor-accessToken",
+  test: "test-accessToken",
+};
+
+module.exports = [
+  {
+    url: "/publicKey",
+    type: "post",
+    response() {
+      return {
+        code: 200,
+        msg: "success",
+        data: {
+          mockServer: true,
+          publicKey:
+            "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBT2vr+dhZElF73FJ6xiP181txKWUSNLPQQlid6DUJhGAOZblluafIdLmnUyKE8mMHhT3R+Ib3ssZcJku6Hn72yHYj/qPkCGFv0eFo7G+GJfDIUeDyalBN0QsuiE/XzPHJBuJDfRArOiWvH0BXOv5kpeXSXM8yTt5Na1jAYSiQ/wIDAQAB",
+        },
+      };
+    },
+  },
+  {
+    url: "/login",
+    type: "post",
+    response(config) {
+      const { username } = config.body;
+      const accessToken = accessTokens[username];
+      if (!accessToken) {
+        return {
+          code: 500,
+          msg: "帐户或密码不正确。",
+        };
+      }
+      return {
+        code: 200,
+        msg: "success",
+        data: { accessToken },
+      };
+    },
+  },
+  {
+    url: "/register",
+    type: "post",
+    response() {
+      return {
+        code: 200,
+        msg: "模拟注册成功",
+      };
+    },
+  },
+  {
+    url: "/userInfo",
+    type: "post",
+    response(config) {
+      const { accessToken } = config.body;
+      let permissions = ["admin"];
+      let username = "admin";
+      if ("admin-accessToken" === accessToken) {
+        permissions = ["admin"];
+        username = "admin";
+      }
+      if ("editor-accessToken" === accessToken) {
+        permissions = ["editor"];
+        username = "editor";
+      }
+      if ("test-accessToken" === accessToken) {
+        permissions = ["admin", "editor"];
+        username = "test";
+      }
+      return {
+        code: 200,
+        msg: "success",
+        data: {
+          permissions,
+          username,
+          "avatar|1": [
+            "https://i.gtimg.cn/club/item/face/img/2/15922_100.gif",
+            "https://i.gtimg.cn/club/item/face/img/8/15918_100.gif",
+          ],
+        },
+      };
+    },
+  },
+  {
+    url: "/logout",
+    type: "post",
+    response() {
+      return {
+        code: 200,
+        msg: "success",
+      };
+    },
+  },
+];

+ 70 - 0
mock/controller/userManagement.js

@@ -0,0 +1,70 @@
+const totalCount = 3;
+const List = [
+  {
+    id: "@id",
+    username: "admin",
+    password: "admin",
+    email: "@email",
+    permissions: ["admin"],
+    datatime: "@datetime",
+  },
+  {
+    id: "@id",
+    username: "editor",
+    password: "editor",
+    email: "@email",
+    permissions: ["editor"],
+    datatime: "@datetime",
+  },
+  {
+    id: "@id",
+    username: "test",
+    password: "test",
+    email: "@email",
+    permissions: ["admin", "editor"],
+    datatime: "@datetime",
+  },
+];
+module.exports = [
+  {
+    url: "/userManagement/getList",
+    type: "post",
+    response(config) {
+      const { title = "", pageNo = 1, pageSize = 20 } = config.body;
+      let mockList = List.filter((item) => {
+        if (title && item.title.indexOf(title) < 0) return false;
+        return true;
+      });
+      const pageList = mockList.filter(
+        (item, index) =>
+          index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
+      );
+      return {
+        code: 200,
+        msg: "success",
+        totalCount,
+        data: pageList,
+      };
+    },
+  },
+  {
+    url: "/userManagement/doEdit",
+    type: "post",
+    response() {
+      return {
+        code: 200,
+        msg: "模拟保存成功",
+      };
+    },
+  },
+  {
+    url: "/userManagement/doDelete",
+    type: "post",
+    response() {
+      return {
+        code: 200,
+        msg: "模拟删除成功",
+      };
+    },
+  },
+];

+ 98 - 0
mock/index.js

@@ -0,0 +1,98 @@
+const chokidar = require("chokidar");
+const bodyParser = require("body-parser");
+const chalk = require("chalk");
+const path = require("path");
+const { mock } = require("mockjs");
+const { baseURL } = require("../src/config");
+const mockDir = path.join(process.cwd(), "mock");
+const { handleMockArray } = require("./utils");
+
+/**
+ *
+ * @param app
+ * @returns {{mockStartIndex: number, mockRoutesLength: number}}
+ */
+const registerRoutes = (app) => {
+  let mockLastIndex;
+  const mocks = [];
+  const mockArray = handleMockArray();
+  mockArray.forEach((item) => {
+    const obj = require(item);
+    mocks.push(...obj);
+  });
+  const mocksForServer = mocks.map((route) => {
+    return responseFake(route.url, route.type, route.response);
+  });
+  for (const mock of mocksForServer) {
+    app[mock.type](mock.url, mock.response);
+    mockLastIndex = app._router.stack.length;
+  }
+  const mockRoutesLength = Object.keys(mocksForServer).length;
+  return {
+    mockRoutesLength: mockRoutesLength,
+    mockStartIndex: mockLastIndex - mockRoutesLength,
+  };
+};
+
+/**
+ *
+ * @param url
+ * @param type
+ * @param respond
+ * @returns {{response(*=, *=): void, type: (*|string), url: RegExp}}
+ */
+const responseFake = (url, type, respond) => {
+  return {
+    url: new RegExp(`${baseURL}${url}`),
+    type: type || "get",
+    response(req, res) {
+      res.status(200);
+      if (JSON.stringify(req.body) !== "{}") {
+        console.log(chalk.green(`> 请求地址:${req.path}`));
+        console.log(chalk.green(`> 请求参数:${JSON.stringify(req.body)}\n`));
+      } else {
+        console.log(chalk.green(`> 请求地址:${req.path}\n`));
+      }
+      res.json(mock(respond instanceof Function ? respond(req, res) : respond));
+    },
+  };
+};
+/**
+ *
+ * @param app
+ */
+module.exports = (app) => {
+  app.use(bodyParser.json());
+  app.use(
+    bodyParser.urlencoded({
+      extended: true,
+    })
+  );
+
+  const mockRoutes = registerRoutes(app);
+  let mockRoutesLength = mockRoutes.mockRoutesLength;
+  let mockStartIndex = mockRoutes.mockStartIndex;
+  chokidar
+    .watch(mockDir, {
+      ignored: /mock-server/,
+      ignoreInitial: true,
+    })
+    .on("all", (event) => {
+      if (event === "change" || event === "add") {
+        try {
+          app._router.stack.splice(mockStartIndex, mockRoutesLength);
+
+          Object.keys(require.cache).forEach((item) => {
+            if (item.includes(mockDir)) {
+              delete require.cache[require.resolve(item)];
+            }
+          });
+          const mockRoutes = registerRoutes(app);
+          mockRoutesLength = mockRoutes.mockRoutesLength;
+          mockStartIndex = mockRoutes.mockStartIndex;
+        } catch (error) {
+          console.log(chalk.red(error));
+        }
+      }
+    });
+};

+ 94 - 0
mock/mockServer.js

@@ -0,0 +1,94 @@
+const chokidar = require("chokidar");
+const bodyParser = require("body-parser");
+const chalk = require("chalk");
+const path = require("path");
+const Mock = require("mockjs");
+const { baseURL } = require("../src/config");
+const mockDir = path.join(process.cwd(), "mock");
+
+/**
+ *
+ * @param app
+ * @returns {{mockStartIndex: number, mockRoutesLength: number}}
+ */
+const registerRoutes = (app) => {
+  let mockLastIndex;
+  const { mocks } = require("./index.js");
+  const mocksForServer = mocks.map((route) => {
+    return responseFake(route.url, route.type, route.response);
+  });
+  for (const mock of mocksForServer) {
+    app[mock.type](mock.url, mock.response);
+    mockLastIndex = app._router.stack.length;
+  }
+  const mockRoutesLength = Object.keys(mocksForServer).length;
+  return {
+    mockRoutesLength: mockRoutesLength,
+    mockStartIndex: mockLastIndex - mockRoutesLength,
+  };
+};
+
+/**
+ *
+ * @param url
+ * @param type
+ * @param respond
+ * @returns {{response(*=, *=): void, type: (*|string), url: RegExp}}
+ */
+const responseFake = (url, type, respond) => {
+  return {
+    url: new RegExp(`${baseURL}${url}`),
+    type: type || "get",
+    response(req, res) {
+      res.status(200);
+      if (JSON.stringify(req.body) !== "{}") {
+        console.log(chalk.green(`> 请求地址:${req.path}`));
+        console.log(chalk.green(`> 请求参数:${JSON.stringify(req.body)}\n`));
+      } else {
+        console.log(chalk.green(`> 请求地址:${req.path}\n`));
+      }
+      res.json(
+        Mock.mock(respond instanceof Function ? respond(req, res) : respond)
+      );
+    },
+  };
+};
+/**
+ *
+ * @param app
+ */
+module.exports = (app) => {
+  app.use(bodyParser.json());
+  app.use(
+    bodyParser.urlencoded({
+      extended: true,
+    })
+  );
+
+  const mockRoutes = registerRoutes(app);
+  let mockRoutesLength = mockRoutes.mockRoutesLength;
+  let mockStartIndex = mockRoutes.mockStartIndex;
+  chokidar
+    .watch(mockDir, {
+      ignored: /mock-server/,
+      ignoreInitial: true,
+    })
+    .on("all", (event) => {
+      if (event === "change" || event === "add") {
+        try {
+          app._router.stack.splice(mockStartIndex, mockRoutesLength);
+
+          Object.keys(require.cache).forEach((item) => {
+            if (item.includes(mockDir)) {
+              delete require.cache[require.resolve(item)];
+            }
+          });
+          const mockRoutes = registerRoutes(app);
+          mockRoutesLength = mockRoutes.mockRoutesLength;
+          mockStartIndex = mockRoutes.mockStartIndex;
+        } catch (error) {
+          console.log(chalk.red(error));
+        }
+      }
+    });
+};

+ 43 - 0
mock/utils/index.js

@@ -0,0 +1,43 @@
+const { Random } = require("mockjs");
+const { join } = require("path");
+const fs = require("fs");
+
+/**
+ * @copyright chuzhixin 1204505056@qq.com
+ * @description 随机生成图片url。
+ * @param width
+ * @param height
+ * @returns {string}
+ */
+function handleRandomImage(width = 50, height = 50) {
+  return `https://picsum.photos/${width}/${height}?random=${Random.guid()}`;
+}
+
+/**
+ * @copyright chuzhixin 1204505056@qq.com
+ * @description 处理所有 controller 模块,npm run serve时在node环境中自动输出controller文件夹下Mock接口,请勿修改。
+ * @returns {[]}
+ */
+function handleMockArray() {
+  const mockArray = [];
+  const getFiles = (jsonPath) => {
+    const jsonFiles = [];
+    const findJsonFile = (path) => {
+      const files = fs.readdirSync(path);
+      files.forEach((item) => {
+        const fPath = join(path, item);
+        const stat = fs.statSync(fPath);
+        if (stat.isDirectory() === true) findJsonFile(item);
+        if (stat.isFile() === true) jsonFiles.push(item);
+      });
+    };
+    findJsonFile(jsonPath);
+    jsonFiles.forEach((item) => mockArray.push(`./controller/${item}`));
+  };
+  getFiles("mock/controller");
+  return mockArray;
+}
+module.exports = {
+  handleRandomImage,
+  handleMockArray,
+};

+ 45 - 0
nginx.conf

@@ -0,0 +1,45 @@
+user  nginx;
+worker_processes  auto;
+pid        /var/run/nginx.pid;
+
+events {
+    use epoll;
+    worker_connections 51200;
+    multi_accept on;
+}
+
+http {
+    include       /etc/nginx/mime.types;
+    default_type  application/octet-stream;
+
+    server_names_hash_bucket_size 512;
+    client_header_buffer_size 32k;
+    large_client_header_buffers 4 32k;
+    client_max_body_size 50m;
+
+    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+                      '$status $body_bytes_sent "$http_referer" '
+                      '"$http_user_agent" "$http_x_forwarded_for"';
+    access_log  /var/log/nginx/access.log  main;
+    sendfile        on;
+    tcp_nopush     on;
+    tcp_nodelay on;
+
+    keepalive_timeout  65;
+
+    # gzip 压缩
+    gzip on;
+    gzip_min_length  1k;
+    gzip_buffers     4 16k;
+    gzip_http_version 1.1;
+    gzip_comp_level 2;
+    gzip_types     text/plain application/javascript application/x-javascript text/javascript text/css application/xml;
+    gzip_vary on;
+    gzip_proxied   expired no-cache no-store private auth;
+    gzip_disable   "MSIE [1-6]\.";
+
+    limit_conn_zone $binary_remote_addr zone=perip:10m;
+    limit_conn_zone $server_name zone=perserver:10m;
+
+    include /etc/nginx/conf.d/*.conf;
+}

+ 46 - 0
nginx.default.conf

@@ -0,0 +1,46 @@
+server {
+    listen       80;
+    server_name  localhost;
+
+    access_log  /data/log/nginx/access.log  main;
+    error_log   /data/log/nginx/error.log;
+
+    # 静态资源
+    location / {
+        root   /data/web;
+        index  index.html index.htm;
+        try_files $uri $uri/ /index.html;
+    }
+
+    # 前端代理
+    location ^~ /后端服务名(比如 opsli-boot) {
+        proxy_pass http://后端服务IP地址:8080;
+        add_header Access-Control-Allow-Origin *;
+        add_header Access-Control-Allow-Credentials: true;
+        add_header Access-Control-Allow-Methods GET,POST,OPTIONS,PUT,DELETE;
+
+        proxy_http_version 1.1;
+        # 连接延时
+        proxy_connect_timeout 3600s;
+        proxy_read_timeout 3600s;
+        proxy_send_timeout 3600s;
+        # IP 穿透
+        proxy_set_header        Host $proxy_host;
+        proxy_set_header        X-Real-IP $remote_addr;
+        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
+        # WebSocket 穿透
+        proxy_set_header Origin "";
+        proxy_set_header Upgrade $http_upgrade;
+        proxy_set_header Connection "upgrade";
+    }
+
+    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
+    #location ~ \.php$ {
+    #    root           html;
+    #    fastcgi_pass   127.0.0.1:9000;
+    #    fastcgi_index  index.php;
+    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
+    #    include        fastcgi_params;
+    #}
+}
+

BIN
node_modules.zip


+ 109 - 0
package.json

@@ -0,0 +1,109 @@
+{
+  "name": "vue-admin-better",
+  "version": "2.1.5",
+  "author": "vue-admin-better",
+  "participants": [],
+  "homepage": "https://chu1204505056.gitee.io/vue-admin-better",
+  "scripts": {
+    "globle": "npm config set registry https://registry.npm.taobao.org && npm install -g yarn && yarn config set registry https://registry.npm.taobao.org && yarn config set ignore-engines true && yarn install",
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "lint": "vue-cli-service lint --fix",
+    "increase-memory-limit": "increase-memory-limit",
+    "postinstall": "patch-package"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/chuzhixin/vue-admin-beautiful.git"
+  },
+  "gitHooks": {
+    "pre-commit": "lint-staged"
+  },
+  "lint-staged": {
+    "*.{js,jsx,vue}": [
+      "vue-cli-service lint",
+      "git add"
+    ]
+  },
+  "dependencies": {
+    "axios": "^1.3.4",
+    "better-scroll": "^2.0.4",
+    "caniuse-lite": "^1.0.30001464",
+    "clipboard": "^2.0.11",
+    "codemirror": "5.45.0",
+    "core-js": "^3.29.0",
+    "crypto-js": "^4.1.1",
+    "dayjs": "^1.11.7",
+    "echarts": "5.4.1",
+    "element-resize-detector": "^1.2.2",
+    "element-ui": "^2.15.13",
+    "file-saver": "^2.0.2",
+    "github-markdown-css": "^5.1.0",
+    "js-cookie": "^2.2.1",
+    "jsencrypt": "^3.3.2",
+    "jsonlint": "^1.6.3",
+    "layouts": "file:layouts",
+    "lodash": "^4.17.21",
+    "maptalks": "^0.49.5",
+    "mapv": "^2.0.62",
+    "marked": "^4.1.1",
+    "mockjs": "^1.1.0",
+    "nprogress": "^0.2.0",
+    "qs": "^6.11.1",
+    "screenfull": "^5.2.0",
+    "sortablejs": "^1.15.0",
+    "vab-icon": "file:vab-icon",
+    "vue": "~2.6.14",
+    "vue-amap": "^0.5.10",
+    "vue-echarts": "5.0.0-beta.0",
+    "vue-qart": "^2.2.0",
+    "vue-router": "^3.5.3",
+    "vue-template-compiler": "~2.6.14",
+    "vuedraggable": "^2.24.1",
+    "vuex": "^3.6.2",
+    "wangeditor": "^4.7.15"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "^4.5.15",
+    "@vue/cli-plugin-eslint": "^4.5.15",
+    "@vue/cli-service": "^4.5.15",
+    "@vue/composition-api": "^1.7.1",
+    "@vue/eslint-config-prettier": "^7.1.0",
+    "babel-eslint": "^10.1.0",
+    "body-parser": "^1.20.2",
+    "chalk": "^4.1.2",
+    "chokidar": "^3.5.3",
+    "eslint": "^7.32.0",
+    "eslint-plugin-prettier": "^4.2.1",
+    "eslint-plugin-vue": "^9.1.1",
+    "filemanager-webpack-plugin": "^8.0.0",
+    "lint-staged": "^13.2.0",
+    "patch-package": "^6.2.2",
+    "plop": "^2.7.4",
+    "prettier": "^2.8.4",
+    "sass": "~1.32.13",
+    "sass-loader": "^10.1.1",
+    "script-loader": "^0.7.2",
+    "stylelint": "^15.2.0",
+    "stylelint-config-prettier": "^9.0.5",
+    "stylelint-config-recess-order": "^4.0.0",
+    "svg-sprite-loader": "^6.0.11",
+    "vue-cropper": "^0.5.5",
+    "webpackbar": "^5.0.2"
+  },
+  "keywords": [
+    "vue",
+    "admin",
+    "dashboard",
+    "element-ui",
+    "vue-admin",
+    "element-admin",
+    "boilerplate",
+    "admin-template",
+    "management-system"
+  ],
+  "engines": {
+    "node": ">=8.9",
+    "npm": ">= 3.0.0"
+  }
+}

+ 26 - 0
patches/element-ui+2.15.13.patch

@@ -0,0 +1,26 @@
+diff --git a/node_modules/element-ui/lib/element-ui.common.js b/node_modules/element-ui/lib/element-ui.common.js
+index dae8b31..04522b0 100644
+--- a/node_modules/element-ui/lib/element-ui.common.js
++++ b/node_modules/element-ui/lib/element-ui.common.js
+@@ -29862,7 +29862,7 @@ function srcvue_type_script_lang_js_noop() {}
+       var file = this.getFile(rawFile);
+       this.onProgress(ev, file, this.uploadFiles);
+       file.status = 'uploading';
+-      file.percentage = ev.percent || 0;
++      file.percentage = (ev === undefined || ev.percent === undefined)?0:ev.percent;
+     },
+     handleSuccess: function handleSuccess(res, rawFile) {
+       var file = this.getFile(rawFile);
+diff --git a/node_modules/element-ui/packages/upload/src/index.vue b/node_modules/element-ui/packages/upload/src/index.vue
+index e735653..e9873ae 100644
+--- a/node_modules/element-ui/packages/upload/src/index.vue
++++ b/node_modules/element-ui/packages/upload/src/index.vue
+@@ -176,7 +176,7 @@ export default {
+       const file = this.getFile(rawFile);
+       this.onProgress(ev, file, this.uploadFiles);
+       file.status = 'uploading';
+-      file.percentage = ev.percent || 0;
++      file.percentage = (ev === undefined || ev.percent === undefined)?0:ev.percent;
+     },
+     handleSuccess(res, rawFile) {
+       const file = this.getFile(rawFile);

+ 16 - 0
prettier.config.js

@@ -0,0 +1,16 @@
+module.exports = {
+  printWidth: 80,
+  tabWidth: 2,
+  useTabs: false,
+  semi: true,
+  singleQuote: false,
+  quoteProps: "as-needed",
+  jsxSingleQuote: false,
+  trailingComma: "es5",
+  bracketSpacing: true,
+  jsxBracketSameLine: false,
+  arrowParens: "always",
+  htmlWhitespaceSensitivity: "ignore",
+  vueIndentScriptAndStyle: true,
+  endOfLine: "lf",
+};

BIN
public/favicon.ico


BIN
public/img/2D弹道1.png


BIN
public/img/2D弹道轨迹.jpg


BIN
public/img/banner.jpg


BIN
public/img/banner.png


BIN
public/img/dd.png


BIN
public/img/img.png


BIN
public/img/img_1.png


BIN
public/img/map.png


BIN
public/img/s01.png


BIN
public/img/s02.png


BIN
public/img/s03.png


BIN
public/img/s04.png


BIN
public/img/weixing.jpg


BIN
public/img/x01.png


BIN
public/img/x02.png


BIN
public/img/x03.png


BIN
public/img/x04.png


BIN
public/img/zha.png


BIN
public/img/zha2.png


BIN
public/img/zha3.png


BIN
public/img/zha4.png


BIN
public/img/zha5.png


BIN
public/img/态势展示.png


BIN
public/img/视角1.png


BIN
public/img/视角2.png


BIN
public/img/视角3.png


BIN
public/img/视角4.png


BIN
public/img/视角5.png


BIN
public/img/视角6.png


BIN
public/img/视角7.png


BIN
public/img/视角8.png


Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff