deploy
4
.browserslistrc
Normal file
@ -0,0 +1,4 @@
|
||||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
||||
|
12
.editorconfig
Normal file
@ -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
|
2
.env.development
Normal file
@ -0,0 +1,2 @@
|
||||
NODE_ENV = development
|
||||
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
1
.env.preview
Normal file
@ -0,0 +1 @@
|
||||
NODE_ENV = preview
|
5
.eslintignore
Normal file
@ -0,0 +1,5 @@
|
||||
src/assets
|
||||
src/icons
|
||||
public
|
||||
dist
|
||||
node_modules
|
26
.eslintrc.js
Normal file
@ -0,0 +1,26 @@
|
||||
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",
|
||||
},
|
||||
parserOptions: {
|
||||
parser: "babel-eslint",
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: [
|
||||
"**/__tests__/*.{j,t}s?(x)",
|
||||
"**/tests/unit/**/*.spec.{j,t}s?(x)",
|
||||
],
|
||||
env: {
|
||||
jest: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
10
.gitattributes
vendored
Normal file
@ -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
|
2
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
patreon: chuzhixin
|
||||
|
18
.gitignore
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
dist
|
||||
.env.local
|
||||
.env.*.local
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
public/video
|
||||
*.zip
|
||||
*.7z
|
||||
/src/layouts/components/zx-layouts
|
35
.stylelintrc.js
Normal file
@ -0,0 +1,35 @@
|
||||
module.exports = {
|
||||
extends: ["stylelint-config-standard", "stylelint-config-recess-order"],
|
||||
rules: {
|
||||
"at-rule-no-unknown": [
|
||||
true,
|
||||
{
|
||||
ignoreAtRules: [
|
||||
"mixin",
|
||||
"extend",
|
||||
"content",
|
||||
"include",
|
||||
"for",
|
||||
"function",
|
||||
"return",
|
||||
],
|
||||
},
|
||||
],
|
||||
"selector-pseudo-element-no-unknown": [
|
||||
true,
|
||||
{
|
||||
ignorePseudoElements: ["v-deep"],
|
||||
},
|
||||
],
|
||||
"selector-pseudo-class-no-unknown": [
|
||||
true,
|
||||
{
|
||||
ignorePseudoClasses: ["export"],
|
||||
},
|
||||
],
|
||||
indentation: 2,
|
||||
"no-descending-specificity": null,
|
||||
"declaration-colon-newline-after": null,
|
||||
},
|
||||
ignoreFiles: ["**/*.js", "dist/*.*", "node_modules", "**/*.ts"],
|
||||
};
|
48
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"[vue]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"editor.quickSuggestions": {
|
||||
"strings": true
|
||||
},
|
||||
"workbench.colorTheme": "One Monokai",
|
||||
"editor.tabSize": 2,
|
||||
"editor.detectIndentation": false,
|
||||
"emmet.triggerExpansionOnTab": true,
|
||||
"editor.formatOnSave": true,
|
||||
"javascript.format.enable": true,
|
||||
"stylelint.enable": true,
|
||||
"css.validate": false,
|
||||
"less.validate": false,
|
||||
"scss.validate": false,
|
||||
"stylelint.autoFixOnSave": true,
|
||||
"git.enableSmartCommit": true,
|
||||
"git.autofetch": true,
|
||||
"git.confirmSync": false,
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"liveServer.settings.donotShowInfoMsg": true,
|
||||
"explorer.confirmDelete": false,
|
||||
"javascript.updateImportsOnFileMove.enabled": "always",
|
||||
"typescript.updateImportsOnFileMove.enabled": "always",
|
||||
"files.exclude": {
|
||||
"**/.idea": true
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[scss]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"editor.suggest.snippetsPreventQuickSuggestions": false
|
||||
}
|
373
LICENSE
Normal file
@ -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.
|
277
README.md
Normal file
@ -0,0 +1,277 @@
|
||||
## 演示地址
|
||||
|
||||
#### - [🚀 演示地址 1: vue-admin-beautiful (横向纵向布局无缝切换)](http://beautiful.panm.cn/vue-admin-beautiful/)
|
||||
|
||||
#### - [🚀 国内备份地址: vue-admin-beautiful](https://chu1204505056.gitee.io/vue-admin-beautiful/)
|
||||
|
||||
#### - [🚀 演示地址 2: vue-admin-clever (常规后台管理布局)](http://beautiful.panm.cn/vue-admin-clever/)
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
|
||||
# 进入项目目录
|
||||
cd vue-admin-beautiful
|
||||
# 安装依赖
|
||||
cnpm i
|
||||
# 本地开发 启动项目
|
||||
cnpm run serve
|
||||
```
|
||||
|
||||
## vue-admin-beautiful 前端讨论群-1 972435319(详细文档加群获取)
|
||||
|
||||
不管您加或者不加 您都可以享受到开源的代码 感谢您的支持 感谢您的信任 群内提供 vue-admin-beautiful-template 基础版本 群内提供详细的基础文档 适合框架快速入门
|
||||
|
||||

|
||||
|
||||
<!-- ## vue-admin-beautiful 前端讨论群-VIP 805808910
|
||||
|
||||
群内问题优先回答 群主每周在线授课 提供脚手架搭建在线指导 组件封装方法指导 NPM 发包开发组件指导(需付费 100,帮助你的同时也帮了群主,感谢信任)群内提供专属 VIP 文档 能快速掌握脚手架搭建 开发工具配置的技巧(其实 50%的重复工作都可以靠工具来完成) 如有需要加作者 QQ 1204505056(加作者的前提是您愿意尊重知识,为人谦逊,不糟蹋开原作者的善良,如果你习惯了白嫖,那我尊重不同的声音,如果你觉得贵,请忽略。。。)
|
||||
|
||||
 -->
|
||||
|
||||
## 友情链接
|
||||
|
||||
#### - [uView 文档(超棒的移动跨端框架,文档详细,上手容易)](https://uviewui.com/)
|
||||
|
||||
#### - [uView 开源地址(uView UI,是 uni-app 生态优秀的 UI 框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水)](https://github.com/YanxinNet/uView/)
|
||||
|
||||
#### - [Element UI 表单设计及代码生成器(可视化表单设计器,一键生成 element 表单)](https://github.com/JakHuang/form-generator/)
|
||||
|
||||
#### - [luch-request(基于 Promise 开发的 uni-app 跨平台、项目级别的请求库,它有更小的体积,易用的 api,方便简单的自定义能力)](https://www.quanzhan.co/luch-request/)
|
||||
|
||||
#### - [pl-table 完美解决 element 万级表格数据渲染卡顿问题](https://github.com/livelyPeng/pl-table)
|
||||
|
||||
## 捐赠
|
||||
|
||||

|
||||
|
||||
## 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" || process.env.NODE_ENV === "preview"
|
||||
? "vab-mock-server"
|
||||
: "http://your.website.com",
|
||||
//标题 (包括初次加载雪花屏的标题 页面的标题 浏览器的标题)
|
||||
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加密
|
||||
loginRSA: 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,
|
||||
//代码生成机生成在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
|
41
README_DClOUD.md
Normal file
@ -0,0 +1,41 @@
|
||||
## 本项目地址
|
||||
|
||||
#### - [🚀 演示地址 1 vue-admin-beautiful ](https://chu1204505056.gitee.io/vue-admin-beautiful/)
|
||||
|
||||
#### - [🚀 演示地址 2 vue-admin-beautiful ](http://beautiful.panm.cn/vue-admin-beautiful/)
|
||||
|
||||
#### - [🚀clever 版本 演示地址 vue-admin-beautiful ](http://beautiful.panm.cn/vue-admin-clever/)
|
||||
|
||||
#### - [🚀 开源地址,感谢 star](https://github.com/chuzhixin/vue-admin-beautiful/)
|
||||
|
||||
#### 学习讨论 QQ 群:972435319 群内提供基础版、集成版、clever 版本、详细文档与视频教程
|
||||
|
||||
#### 付费群
|
||||
|
||||

|
||||
|
||||
## 友情链接
|
||||
|
||||
#### - [uView 文档(超棒的移动跨端框架,文档详细,上手容易)](https://uviewui.com/)
|
||||
|
||||
#### - [uView 开源地址(uView UI,是 uni-app 生态优秀的 UI 框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水)](https://github.com/YanxinNet/uView/)
|
||||
|
||||
#### - [luch-request(基于 Promise 开发的 uni-app 跨平台、项目级别的请求库,它有更小的体积,易用的 api,方便简单的自定义能力)](https://www.quanzhan.co/luch-request/)
|
||||
|
||||
## 运行步骤,严格按步骤来
|
||||
|
||||
```bash
|
||||
|
||||
# 进入项目目录
|
||||
cd vue-admin-beautiful
|
||||
# 安装依赖,一定要cnpm i,别听网上乱七八糟的回答,本项目始终基于最新的package版本,cnpm不会出现任何问题,置于怎么安装cnpm自行百度
|
||||
cnpm i
|
||||
# 本地开发 启动项目
|
||||
cnpm run serve
|
||||
```
|
||||
|
||||
#### <font color="red">已付费置顶 烦请小号刷差评的放过 我也需要养家糊口 也祝您财运亨通 好不好用请看演示地址 保留版权信息可免费商用(页面所有版权信息不付费也可完全删除) ,群内提供详细的视频与文档教程,由于置顶费用较高,如有需要在本页加广告的朋友可以联系我 QQ 1204505056</font>
|
||||
|
||||
#### github 标星增长量统计
|
||||
|
||||
[](https://github.com/chuzhixin/vue-admin-beautiful)
|
21
SECURITY.md
Normal file
@ -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
babel.config.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ["@vue/cli-plugin-babel/preset"],
|
||||
};
|
17
deploy.sh
Normal file
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
npm run build:preview
|
||||
cd dist
|
||||
touch .nojekyll
|
||||
git init
|
||||
git add -A
|
||||
git commit -m 'deploy'
|
||||
git push -f "https://${access_token}@gitee.com/chu1204505056/vue-admin-beautiful.git" master:gh-pages
|
||||
start "https://gitee.com/chu1204505056/vue-admin-beautiful/pages"
|
||||
git push -f "https://${access_token}@github.com/chuzhixin/vue-admin-beautiful.git" master:gh-pages
|
||||
cd -
|
||||
exec /bin/bash
|
||||
|
||||
|
||||
|
||||
|
70
http/mock.http
Normal file
@ -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
|
||||
###
|
41
mock/controller/ad.js
Normal file
@ -0,0 +1,41 @@
|
||||
const data = [
|
||||
{
|
||||
title:
|
||||
"作为一个程序员,我迄今为止最骄傲的事情:2020年7月10日,vue/cli4作者蒋豪群采纳了我的对sass-loader 9.0全局注入变量的文档修改建议,以后全世界都能看到我的名字了,这远比vue-admin-beautiful更让我有成就感,感谢shaonialife的帮助。",
|
||||
url: "https://github.com/vuejs/vue-cli/blob/master/docs/zh/guide/css.md",
|
||||
},
|
||||
{
|
||||
title:
|
||||
"近日发现一个名为OKMG芒果源码的网站公然出售vue-admin-beautiful的开源代码,在此向大家说明,框架开源版本永久免费,请勿上当受骗。",
|
||||
url:
|
||||
"//shang.qq.com/wpa/qunwpa?idkey=14f123ac6d4ef3122bbb60d4693f1d8c951a50be2296951efb12d5ab1642f36b",
|
||||
},
|
||||
{
|
||||
title: "uView UI:全面的组件和便捷的工具会让您信手拈来,如鱼得水。",
|
||||
url: "https://uviewui.com/",
|
||||
},
|
||||
{
|
||||
title:
|
||||
"认认真真编程,踏踏实实做人;静坐常思己过,闲谈不论人非;希望使用vue-admin-beautiful框架的每个人,无论过程怎样,结局都是美好的。",
|
||||
url:
|
||||
"//shang.qq.com/wpa/qunwpa?idkey=14f123ac6d4ef3122bbb60d4693f1d8c951a50be2296951efb12d5ab1642f36b",
|
||||
},
|
||||
{
|
||||
title: "vue-admin-beautiful前端讨论群-1:972435319",
|
||||
url:
|
||||
"//shang.qq.com/wpa/qunwpa?idkey=14f123ac6d4ef3122bbb60d4693f1d8c951a50be2296951efb12d5ab1642f36b",
|
||||
},
|
||||
];
|
||||
export default [
|
||||
{
|
||||
url: "/ad/getList",
|
||||
type: "get",
|
||||
response: () => {
|
||||
return {
|
||||
code: 200,
|
||||
msg: "success",
|
||||
data,
|
||||
};
|
||||
},
|
||||
},
|
||||
];
|
163
mock/controller/changeLog.js
Normal file
@ -0,0 +1,163 @@
|
||||
const data = [
|
||||
{
|
||||
content: "在github上获得了第一个star,感恩一位名叫Bequiet2014的github用户",
|
||||
timestamp: "2020-03-23",
|
||||
},
|
||||
{
|
||||
content: "增加更换主题功能",
|
||||
timestamp: "2020-04-10",
|
||||
},
|
||||
{
|
||||
content: "大幅精简代码",
|
||||
timestamp: "2020-04-14",
|
||||
},
|
||||
{
|
||||
content: "修复群友反馈的bug",
|
||||
timestamp: "2020-04-16",
|
||||
},
|
||||
{
|
||||
content: "剔除maptalks",
|
||||
timestamp: "2020-04-17",
|
||||
},
|
||||
{
|
||||
content:
|
||||
"换行符统一修改为lf 支持苹果 linux windows协同开发 强制开启最严格eslint规则 不要哭 严格是有好处的",
|
||||
timestamp: "2020-04-17",
|
||||
},
|
||||
{
|
||||
content: "彻底完成手机端适配,记录这一天熬夜到了晚上三点",
|
||||
timestamp: "2020-04-18",
|
||||
},
|
||||
{
|
||||
content:
|
||||
"删除babel-polyfill 提高打包速度 减少压缩体积(放弃ie是这个项目做出的最伟大的决定)",
|
||||
timestamp: "2020-04-18",
|
||||
},
|
||||
{
|
||||
content: "源码精简至800k",
|
||||
timestamp: "2020-04-19",
|
||||
},
|
||||
{
|
||||
content: "添加视频播放器组件",
|
||||
timestamp: "2020-04-20",
|
||||
},
|
||||
{
|
||||
content: "修复路由懒加载 完善主题配色",
|
||||
timestamp: "2020-04-22",
|
||||
},
|
||||
{
|
||||
content: "修复全局axios拦截 加快动画展示效果 修改登录页样式",
|
||||
timestamp: "2020-04-24",
|
||||
},
|
||||
{
|
||||
content: "简化权限与登录逻辑 更新mockServer",
|
||||
timestamp: "2020-04-25",
|
||||
},
|
||||
{
|
||||
content: "优化登录退出逻辑 代码更清晰 退出不再重载网页 改为重载路由形式",
|
||||
timestamp: "2020-04-26",
|
||||
},
|
||||
{
|
||||
content: "无端的指责只会让我更加努力 修复sidebar 简化permission",
|
||||
timestamp: "2020-04-28",
|
||||
},
|
||||
{
|
||||
content: "又是一个深夜 实现了表格增删改查的一键生成",
|
||||
timestamp: "2020-04-30",
|
||||
},
|
||||
{
|
||||
content: "大幅优化tagsview标签动画",
|
||||
timestamp: "2020-05-02",
|
||||
},
|
||||
{
|
||||
content: "三种图标组件实现mock模拟分页",
|
||||
timestamp: "2020-05-03",
|
||||
},
|
||||
{
|
||||
content: "添加了markdown编辑器组件",
|
||||
timestamp: "2020-05-04",
|
||||
},
|
||||
{
|
||||
content: "添加stylelint-plus自动规整排序样式",
|
||||
timestamp: "2020-05-06",
|
||||
},
|
||||
{
|
||||
content: "添加商城模板",
|
||||
timestamp: "2020-05-12",
|
||||
},
|
||||
{
|
||||
content: "github标星超过1000 感恩",
|
||||
timestamp: "2020-05-13",
|
||||
},
|
||||
{
|
||||
content: "添加验证码组件",
|
||||
timestamp: "2020-05-14",
|
||||
},
|
||||
{
|
||||
content: "修复横向菜单bug",
|
||||
timestamp: "2020-05-16",
|
||||
},
|
||||
{
|
||||
content: "又被人骂了 挺好的 让我下定决心重写了tagsBar",
|
||||
timestamp: "2020-05-20",
|
||||
},
|
||||
{
|
||||
content: "仿ant-design 添加雪花屏",
|
||||
timestamp: "2020-05-26",
|
||||
},
|
||||
{
|
||||
content: "添加人员管理模块",
|
||||
timestamp: "2020-06-02",
|
||||
},
|
||||
{
|
||||
content: "github标星超过2000 感恩",
|
||||
timestamp: "2020-06-03",
|
||||
},
|
||||
{
|
||||
content: "添加炫酷地图组件",
|
||||
timestamp: "2020-06-11",
|
||||
},
|
||||
{
|
||||
content: "抽离更多公共配置,框架使用更顺手",
|
||||
timestamp: "2020-06-19",
|
||||
},
|
||||
{
|
||||
content: "彻底完成了tagsbar多标签页的重构",
|
||||
timestamp: "2020-06-22",
|
||||
},
|
||||
{
|
||||
content: "感恩github标星过3.0K 祝大家端午节快乐",
|
||||
timestamp: "2020-06-25",
|
||||
},
|
||||
{
|
||||
content: "彻底重构了SideBar与TopBar 大幅精简dom渲染逻辑 全球首发",
|
||||
timestamp: "2020-06-25",
|
||||
},
|
||||
{
|
||||
content: "添加菜单管理",
|
||||
timestamp: "2020-07-7",
|
||||
},
|
||||
{
|
||||
content: "首次采用sass-loader 9.0写法,感谢github用户 shaonialife",
|
||||
timestamp: "2020-07-7",
|
||||
},
|
||||
{
|
||||
content: "添加vue-amap组件",
|
||||
timestamp: "2020-07-11",
|
||||
},
|
||||
];
|
||||
|
||||
export default [
|
||||
{
|
||||
url: "/changeLog/getList",
|
||||
type: "post",
|
||||
response: (config) => {
|
||||
return {
|
||||
code: 200,
|
||||
msg: "success",
|
||||
totalCount: 999,
|
||||
data: data,
|
||||
};
|
||||
},
|
||||
},
|
||||
];
|
328
mock/controller/colorfulIcon.js
Normal file
@ -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",
|
||||
];
|
||||
export default [
|
||||
{
|
||||
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
mock/controller/goodsDetail.js
Normal file
@ -0,0 +1,42 @@
|
||||
import { mock } from "mockjs";
|
||||
|
||||
export default [
|
||||
{
|
||||
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
mock/controller/goodsList.js
Normal file
@ -0,0 +1,43 @@
|
||||
import { mock } from "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],
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export default [
|
||||
{
|
||||
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
mock/controller/icon.js
Normal file
@ -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",
|
||||
];
|
||||
export default [
|
||||
{
|
||||
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
mock/controller/menuManagement.js
Normal file
@ -0,0 +1,51 @@
|
||||
export default [
|
||||
{
|
||||
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: "模拟删除成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
];
|
40
mock/controller/notice.js
Normal file
@ -0,0 +1,40 @@
|
||||
const data = [
|
||||
{
|
||||
title:
|
||||
"认认真真编程,踏踏实实做人;静坐常思己过,闲谈不论人非;希望使用vue-admin-beautiful框架的每个人,无论过程怎样,结局都是美好的。。。",
|
||||
closable: false,
|
||||
type: "success",
|
||||
},
|
||||
{
|
||||
title:
|
||||
"作者寄语:感谢Star,感恩相遇,愿世间美好与我们环环相扣,加油!屏幕前的我们,打破桎梏,坚守初心。其实人生改变命运的机会并没有太多,我们并不是不优秀,我们也并不是一无是处,我们也希望驻足山巅被众人仰望,也许我们缺少的只是一个机会,缺少的只是生命中的导师,我希望这个框架帮助到更多的人,希望有一天,我们面试的时候不再胆怯,希望有一天别人看到的不仅仅是你的努力,还有你的功成名就,出人头地。",
|
||||
closable: false,
|
||||
type: "warning",
|
||||
},
|
||||
{
|
||||
title:
|
||||
"鸣谢:尤雨溪、蒋豪群、element-ui、唐金州、花裤衩、贤心、iView、uView的开源项目给我带来的很多的灵感,弱小的人才习惯嘲讽与否定,内心强大的人从不吝啬赞美与鼓励,人生在世,得到每个人的认可几乎是痴心妄想,我也只是一条略懂前端的咸鱼,可我仍一直怀揣着改变世界的梦想,希望我们每个人,不管过程怎样,结局都是美好的。",
|
||||
closable: false,
|
||||
type: "success",
|
||||
},
|
||||
{
|
||||
title:
|
||||
"随笔:我一直在寻找开源的真谛,我一直再想什么是开源,我一开始觉得免费就是开源,好像又不是。我理解的开源是:你也开源,我也开源,大家一起贡献,相互帮助。我最担心的事情是:我一个小人物,去伺候一众的伸手党,我想,这不是开源该有的氛围。我还太年轻,不懂什么是格局,我只知道,无私的帮助他人,能给我带来快乐,却不能给我带来收入,当然,有时候,快乐对我来说就已经足够了。可惜我是一个人,没有精力帮助到每一个人,可惜这个世界需要赚钱,才能过上平凡的生活,可惜了我的梦想,这个物欲横流的时代,理想主义的我们,即使内心坚决如铁,也似乎寸步难行。",
|
||||
closable: false,
|
||||
type: "success",
|
||||
},
|
||||
];
|
||||
|
||||
export default [
|
||||
{
|
||||
url: "/notice/getList",
|
||||
type: "post",
|
||||
response: () => {
|
||||
return {
|
||||
code: 200,
|
||||
msg: "success",
|
||||
data,
|
||||
};
|
||||
},
|
||||
},
|
||||
];
|
42
mock/controller/personalCenter.js
Normal file
@ -0,0 +1,42 @@
|
||||
import { mock } from "mockjs";
|
||||
|
||||
export default [
|
||||
{
|
||||
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
mock/controller/remixIcon.js
Normal file
55
mock/controller/roleManagement.js
Normal file
@ -0,0 +1,55 @@
|
||||
import { mock } from "mockjs";
|
||||
const totalCount = 2;
|
||||
const List = [
|
||||
{
|
||||
id: "@id",
|
||||
permission: "admin",
|
||||
},
|
||||
{
|
||||
id: "@id",
|
||||
permission: "editor",
|
||||
},
|
||||
];
|
||||
export default [
|
||||
{
|
||||
url: "/roleManagement/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: "/roleManagement/doEdit",
|
||||
type: "post",
|
||||
response: (config) => {
|
||||
return {
|
||||
code: 200,
|
||||
msg: "模拟保存成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "/roleManagement/doDelete",
|
||||
type: "post",
|
||||
response: (config) => {
|
||||
return {
|
||||
code: 200,
|
||||
msg: "模拟删除成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
];
|
426
mock/controller/router.js
Normal file
@ -0,0 +1,426 @@
|
||||
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/personnelManagement/userManagement/index",
|
||||
meta: { title: "用户管理" },
|
||||
},
|
||||
{
|
||||
path: "roleManagement",
|
||||
name: "RoleManagement",
|
||||
component: "views/personnelManagement/roleManagement/index",
|
||||
meta: { title: "角色管理" },
|
||||
},
|
||||
{
|
||||
path: "menuManagement",
|
||||
name: "MenuManagement",
|
||||
component: "views/personnelManagement/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: "excel",
|
||||
component: "EmptyLayout",
|
||||
redirect: "noRedirect",
|
||||
name: "Excel",
|
||||
meta: {
|
||||
title: "Excel",
|
||||
permissions: ["admin"],
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "exportExcel",
|
||||
component: "views/vab/excel/exportExcel",
|
||||
name: "ExportExcel",
|
||||
meta: { title: "导出Excel" },
|
||||
},
|
||||
{
|
||||
path: "exportSelectedExcel",
|
||||
component: "views/vab/excel/exportSelectExcel",
|
||||
name: "ExportSelectedExcel",
|
||||
meta: { title: "导出选中行" },
|
||||
},
|
||||
{
|
||||
path: "exportMergeHeaderExcel",
|
||||
component: "views/vab/excel/exportMergeHeaderExcel",
|
||||
name: "ExportMergeHeaderExcel",
|
||||
meta: { title: "导出合并" },
|
||||
},
|
||||
{
|
||||
path: "uploadExcel",
|
||||
component: "views/vab/excel/uploadExcel",
|
||||
name: "UploadExcel",
|
||||
meta: { title: "上传Excel" },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
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" },
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
export default [
|
||||
{
|
||||
url: "/menu/navigate",
|
||||
type: "post",
|
||||
response: () => {
|
||||
return { code: 200, msg: "success", data: data };
|
||||
},
|
||||
},
|
||||
];
|
88
mock/controller/table.js
Normal file
@ -0,0 +1,88 @@
|
||||
import { mock } from "mockjs";
|
||||
import { handleRandomImage } from "../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)",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export default [
|
||||
{
|
||||
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) => {
|
||||
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,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "/table/doEdit",
|
||||
type: "post",
|
||||
response: (config) => {
|
||||
return {
|
||||
code: 200,
|
||||
msg: "模拟保存成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
url: "/table/doDelete",
|
||||
type: "post",
|
||||
response: (config) => {
|
||||
return {
|
||||
code: 200,
|
||||
msg: "模拟删除成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
];
|
54
mock/controller/tree.js
Normal file
@ -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: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
export default [
|
||||
{
|
||||
url: "/tree/list",
|
||||
type: "post",
|
||||
response: () => {
|
||||
return { code: 200, msg: "success", data };
|
||||
},
|
||||
},
|
||||
];
|
14
mock/controller/upload.js
Normal file
@ -0,0 +1,14 @@
|
||||
const data = [];
|
||||
export default [
|
||||
{
|
||||
url: "/upload",
|
||||
type: "post",
|
||||
response: (config) => {
|
||||
return {
|
||||
code: 200,
|
||||
msg: "success",
|
||||
data: data,
|
||||
};
|
||||
},
|
||||
},
|
||||
];
|
95
mock/controller/user.js
Normal file
@ -0,0 +1,95 @@
|
||||
import { handleRandomImage } from "../utils";
|
||||
const accessTokens = {
|
||||
admin: "admin-accessToken",
|
||||
editor: "editor-accessToken",
|
||||
test: "test-accessToken",
|
||||
};
|
||||
|
||||
export default [
|
||||
{
|
||||
url: "/publicKey",
|
||||
type: "post",
|
||||
response: (config) => {
|
||||
return {
|
||||
code: 200,
|
||||
msg: "success",
|
||||
data: {
|
||||
mockServer: true,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
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
mock/controller/userManagement.js
Normal file
@ -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",
|
||||
},
|
||||
];
|
||||
export default [
|
||||
{
|
||||
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: "模拟删除成功",
|
||||
};
|
||||
},
|
||||
},
|
||||
];
|
35
mock/index.js
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @copyright chuzhixin 1204505056@qq.com
|
||||
* @description 导入所有 controller 模块,npm run serve时在node环境中自动输出controller文件夹下Mock接口,请勿修改。
|
||||
*/
|
||||
|
||||
import { handleMockArray } from "./utils";
|
||||
import chalk from "chalk";
|
||||
import fs from "fs";
|
||||
import { baseURL, devPort, httpRequestFile } from "../src/config/settings";
|
||||
|
||||
const mocks = [];
|
||||
const mockArray = handleMockArray();
|
||||
|
||||
if (httpRequestFile) {
|
||||
fs.writeFile("./http/mock.http", "", {}, function (err) {
|
||||
if (err) throw err;
|
||||
});
|
||||
}
|
||||
mockArray.forEach(async (item) => {
|
||||
const obj = require(item).default;
|
||||
await mocks.push(...obj);
|
||||
if (httpRequestFile) {
|
||||
obj.forEach((item) => {
|
||||
fs.appendFile(
|
||||
"./http/mock.http",
|
||||
`\r\n###${item.url}###\r\POST http://localhost:${devPort}/${baseURL}${item.url}\r\nContent-Type: application/x-www-form-urlencoded\r\n###\r\n`,
|
||||
(error) => {
|
||||
if (error)
|
||||
return chalk.red(`\n > 追加HTTP Request失败${error.message}`);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
export default mocks;
|
94
mock/mockServer.js
Normal file
@ -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/settings");
|
||||
const mockDir = path.join(process.cwd(), "mock");
|
||||
|
||||
/**
|
||||
*
|
||||
* @param app
|
||||
* @returns {{mockStartIndex: number, mockRoutesLength: number}}
|
||||
*/
|
||||
function registerRoutes(app) {
|
||||
let mockLastIndex;
|
||||
const { default: 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) {
|
||||
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) => {
|
||||
require("@babel/register");
|
||||
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));
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
53
mock/static.js
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @copyright chuzhixin 1204505056@qq.com
|
||||
* @description 导入所有 controller 模块,浏览器环境中自动输出controller文件夹下Mock接口,请勿修改。
|
||||
*/
|
||||
import Mock from "mockjs";
|
||||
import { paramObj } from "../src/utils";
|
||||
|
||||
const mocks = [];
|
||||
const files = require.context("./controller", false, /\.js$/);
|
||||
|
||||
files.keys().forEach((key) => {
|
||||
const obj = files(key).default;
|
||||
mocks.push(...obj);
|
||||
});
|
||||
|
||||
export function mockXHR() {
|
||||
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send;
|
||||
Mock.XHR.prototype.send = function () {
|
||||
if (this.custom.xhr) {
|
||||
this.custom.xhr.withCredentials = this.withCredentials || false;
|
||||
|
||||
if (this.responseType) {
|
||||
this.custom.xhr.responseType = this.responseType;
|
||||
}
|
||||
}
|
||||
this.proxy_send(...arguments);
|
||||
};
|
||||
|
||||
function XHR2ExpressReqWrap(respond) {
|
||||
return function (options) {
|
||||
let result = null;
|
||||
if (respond instanceof Function) {
|
||||
const { body, type, url } = options;
|
||||
result = respond({
|
||||
method: type,
|
||||
body: JSON.parse(body),
|
||||
query: paramObj(url),
|
||||
});
|
||||
} else {
|
||||
result = respond;
|
||||
}
|
||||
return Mock.mock(result);
|
||||
};
|
||||
}
|
||||
|
||||
for (const i of mocks) {
|
||||
Mock.mock(
|
||||
new RegExp(i.url),
|
||||
i.type || "get",
|
||||
XHR2ExpressReqWrap(i.response)
|
||||
);
|
||||
}
|
||||
}
|
39
mock/utils/index.js
Normal file
@ -0,0 +1,39 @@
|
||||
import { Random } from "mockjs";
|
||||
import { join } from "path";
|
||||
import fs from "fs";
|
||||
|
||||
/**
|
||||
* @copyright chuzhixin 1204505056@qq.com
|
||||
* @description 随机生成图片url。
|
||||
* @param width
|
||||
* @param height
|
||||
* @returns {string}
|
||||
*/
|
||||
export 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 {[]}
|
||||
*/
|
||||
export 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;
|
||||
}
|
121
package.json
Normal file
@ -0,0 +1,121 @@
|
||||
{
|
||||
"name": "vue-admin-beautiful",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"author": "chuzhixin",
|
||||
"participants": [],
|
||||
"homepage": "https://chu1204505056.gitee.io/vue-admin-beautiful",
|
||||
"scripts": {
|
||||
"serve": "npm run helper&&vue-cli-service serve",
|
||||
"build": "npm run helper&&vue-cli-service build",
|
||||
"build:preview": "npm run helper&&vue-cli-service build --mode preview",
|
||||
"globle": "npm install -g cnpm --registry=https://registry.npm.taobao.org&&cnpm i rimraf npm-check-updates nrm -g&&rimraf node_modules&&cnpm i",
|
||||
"lint": "vue-cli-service lint --fix",
|
||||
"lint:style": "stylelint **/*.{vue,css,scss} --fix",
|
||||
"inspect": "vue-cli-service inspect",
|
||||
"template": "plop",
|
||||
"clear": "rimraf node_modules&&cnpm i&&increase-memory-limit",
|
||||
"use:npm": "nrm use npm",
|
||||
"use:taobao": "nrm use taobao",
|
||||
"update": "ncu -u --concurrency 10 --timeout 80000&&cnpm i",
|
||||
"update:globle": "ncu -g --concurrency 10 --timeout 80000",
|
||||
"svgo": "svgo -f src/remixIcon/svg --config=svgo.yml",
|
||||
"push": "start ./push.sh",
|
||||
"deploy": "start ./deploy.sh",
|
||||
"increase-memory-limit": "increase-memory-limit",
|
||||
"helper": "node node_modules/zx-layouts"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/chuzhixin/vue-admin-beautiful.git"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"src/**/*.{js,vue}": [
|
||||
"eslint --fix",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.19.2",
|
||||
"better-scroll": "^1.15.2",
|
||||
"clipboard": "^2.0.6",
|
||||
"codemirror": "^5.55.0",
|
||||
"core-js": "^3.6.5",
|
||||
"dayjs": "^1.8.29",
|
||||
"echarts": "^4.8.0",
|
||||
"echarts-wordcloud": "^1.1.3",
|
||||
"element-ui": "^2.13.2",
|
||||
"file-saver": "^2.0.2",
|
||||
"js-cookie": "^2.2.1",
|
||||
"jsencrypt": "^3.0.0-rc.1",
|
||||
"jsonlint": "^1.6.3",
|
||||
"lodash": "^4.17.19",
|
||||
"maptalks": "^0.47.5",
|
||||
"mapv": "^2.0.56",
|
||||
"nprogress": "^0.2.0",
|
||||
"qs": "^6.9.4",
|
||||
"screenfull": "^5.0.2",
|
||||
"vue": "^2.6.11",
|
||||
"vue-amap": "^0.5.10",
|
||||
"vue-echarts": "^5.0.0-beta.0",
|
||||
"vue-qart": "^2.2.0",
|
||||
"vue-router": "^3.3.4",
|
||||
"vuedraggable": "^2.24.0",
|
||||
"vuex": "^3.5.1",
|
||||
"xlsx": "^0.16.3",
|
||||
"zx-comparison": "^1.0.3",
|
||||
"zx-count": "^0.3.7",
|
||||
"zx-icon": "^1.1.1",
|
||||
"zx-keel": "^0.9.4",
|
||||
"zx-layouts": "^0.5.7",
|
||||
"zx-magnifie": "^0.4.0",
|
||||
"zx-markdown-editor": "^0.0.2",
|
||||
"zx-player": "^0.9.6",
|
||||
"zx-quill": "^0.0.2",
|
||||
"zx-templates": "^0.0.10",
|
||||
"zx-verify": "^0.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/register": "^7.10.4",
|
||||
"@vue/cli-plugin-babel": "^4.4.6",
|
||||
"@vue/cli-plugin-eslint": "^4.4.6",
|
||||
"@vue/cli-plugin-router": "^4.4.6",
|
||||
"@vue/cli-plugin-vuex": "^4.4.6",
|
||||
"@vue/cli-service": "^4.4.6",
|
||||
"@vue/eslint-config-prettier": "^6.0.0",
|
||||
"autoprefixer": "^9.8.5",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"compression-webpack-plugin": "^4.0.0",
|
||||
"eslint": "^7.4.0",
|
||||
"eslint-plugin-prettier": "^3.1.4",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"filemanager-webpack-plugin": "^2.0.5",
|
||||
"husky": "^4.2.5",
|
||||
"image-webpack-loader": "^6.0.0",
|
||||
"increase-memory-limit": "^1.0.7",
|
||||
"lint-staged": "^10.2.11",
|
||||
"mockjs": "^1.1.0",
|
||||
"plop": "^2.7.1",
|
||||
"prettier": "^2.0.5",
|
||||
"sass": "^1.26.10",
|
||||
"sass-loader": "^9.0.2",
|
||||
"script-loader": "^0.7.2",
|
||||
"stylelint": "^13.6.1",
|
||||
"stylelint-config-recess-order": "^2.0.4",
|
||||
"stylelint-config-standard": "^20.0.0",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"svg-sprite-loader": "^5.0.0",
|
||||
"svgo": "^1.3.2",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"webpackbar": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.9",
|
||||
"npm": ">= 3.0.0"
|
||||
}
|
||||
}
|
13
plopfile.js
Normal file
@ -0,0 +1,13 @@
|
||||
const viewGenerator = require("zx-templates/view/prompt");
|
||||
const curdGenerator = require("zx-templates/curd/prompt");
|
||||
const componentGenerator = require("zx-templates/component/prompt");
|
||||
const mockGenerator = require("zx-templates/mock/prompt");
|
||||
const vuexGenerator = require("zx-templates/vuex/prompt");
|
||||
|
||||
module.exports = (plop) => {
|
||||
plop.setGenerator("view", viewGenerator);
|
||||
plop.setGenerator("curd", curdGenerator);
|
||||
plop.setGenerator("component", componentGenerator);
|
||||
plop.setGenerator("mock&api", mockGenerator);
|
||||
plop.setGenerator("vuex", vuexGenerator);
|
||||
};
|
5
postcss.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
15
prettier.config.js
Normal file
@ -0,0 +1,15 @@
|
||||
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",
|
||||
vueIndentScriptAndStyle: false,
|
||||
endOfLine: "lf",
|
||||
};
|
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
public/favicon_backup.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
47
public/index.html
Normal file
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-cmn-Hans">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
|
||||
<title><%= VUE_APP_TITLE %></title>
|
||||
<meta
|
||||
name="keywords"
|
||||
content="vab,vab官网,后台管理框架,vue后台管理框架,vue-admin-beautiful,vue-admin-beautiful官网,vue-admin-beautiful文档,vue-element-admin,vue-element-admin官网,vue-element-admin文档,vue-admin,vue-admin官网,vue-admin文档"
|
||||
/>
|
||||
<meta
|
||||
name="description"
|
||||
content="<%= VUE_APP_TITLE %>官网与文档基于vue-admin-beautiful构建,简称vab(是一款超棒的vue+element中后台前端快速开发框架),QQ群972435319,作者:<%= VUE_APP_AUTHOR %>"
|
||||
/>
|
||||
<meta name="author" content="<%= VUE_APP_AUTHOR %>" />
|
||||
<link rel="stylesheet" href="<%= BASE_URL %>static/css/loading.css" />
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function () {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?7174bade1219f9cc272e7978f9523fc8";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
非常抱歉鉴于安全考量,您无法查看<%= VUE_APP_TITLE %>
|
||||
源代码,该系统基于vue-admin-beautiful开发
|
||||
</noscript>
|
||||
<div id="vue-admin-beautiful">
|
||||
<div class="first-loading-wrp">
|
||||
<div class="loading-wrp">
|
||||
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
|
||||
</div>
|
||||
<h1><%= VUE_APP_TITLE %></h1>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
/^http(s*):\/\//.test(location.href) ||
|
||||
alert("基于vue-admin-beautiful开发的项目需要部署到服务器下访问");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
96
public/static/css/loading.css
Normal file
@ -0,0 +1,96 @@
|
||||
.first-loading-wrp {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 90vh;
|
||||
min-height: 90vh;
|
||||
}
|
||||
|
||||
.first-loading-wrp > h1 {
|
||||
font-size: 30px;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.first-loading-wrp .loading-wrp {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 98px;
|
||||
}
|
||||
|
||||
.dot {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
font-size: 64px;
|
||||
transform: rotate(45deg);
|
||||
animation: antRotate 1.2s infinite linear;
|
||||
}
|
||||
|
||||
.dot i {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background-color: #1890ff;
|
||||
border-radius: 100%;
|
||||
opacity: 0.3;
|
||||
transform: scale(0.75);
|
||||
transform-origin: 50% 50%;
|
||||
animation: antSpinMove 1s infinite linear alternate;
|
||||
}
|
||||
|
||||
.dot i:nth-child(1) {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.dot i:nth-child(2) {
|
||||
top: 0;
|
||||
right: 0;
|
||||
-webkit-animation-delay: 0.4s;
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.dot i:nth-child(3) {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
-webkit-animation-delay: 0.8s;
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
|
||||
.dot i:nth-child(4) {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
-webkit-animation-delay: 1.2s;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
|
||||
@keyframes antRotate {
|
||||
to {
|
||||
-webkit-transform: rotate(405deg);
|
||||
transform: rotate(405deg);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes antRotate {
|
||||
to {
|
||||
-webkit-transform: rotate(405deg);
|
||||
transform: rotate(405deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSpinMove {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes antSpinMove {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
13
push.sh
Normal file
@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
git init
|
||||
git add -A
|
||||
git commit -m 'deploy'
|
||||
git push -f "https://${access_token}@github.com/chuzhixin/vue-admin-beautiful.git" master
|
||||
git push -f "https://${access_token}@gitee.com/chu1204505056/vue-admin-beautiful.git" master
|
||||
start "https://github.com/chuzhixin/vue-admin-beautiful"
|
||||
exec /bin/bash
|
||||
|
||||
|
||||
|
||||
|
12
src/App.vue
Normal file
@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<div id="vue-admin-beautiful">
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "App",
|
||||
mounted() {},
|
||||
};
|
||||
</script>
|
9
src/api/ad.js
Normal file
@ -0,0 +1,9 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getList(data) {
|
||||
return request({
|
||||
url: "/ad/getList",
|
||||
method: "get",
|
||||
data,
|
||||
});
|
||||
}
|
9
src/api/changeLog.js
Normal file
@ -0,0 +1,9 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getList(data) {
|
||||
return request({
|
||||
url: "/changeLog/getList",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
9
src/api/colorfulIcon.js
Normal file
@ -0,0 +1,9 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getIconList(data) {
|
||||
return request({
|
||||
url: "/colorfulIcon/getList",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
25
src/api/face.js
Normal file
@ -0,0 +1,25 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getList(data) {
|
||||
return request({
|
||||
url: "/face/list",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function doEdit(data) {
|
||||
return request({
|
||||
url: "/face/edit",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function doDelete(data) {
|
||||
return request({
|
||||
url: "/face/delete",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
20
src/api/github.js
Normal file
@ -0,0 +1,20 @@
|
||||
import request from "axios";
|
||||
|
||||
export function getRepos(params) {
|
||||
return request({
|
||||
url: "https://api.github.com/repos/chuzhixin/vue-admin-beautiful",
|
||||
method: "get",
|
||||
params,
|
||||
timeout: 10000,
|
||||
});
|
||||
}
|
||||
|
||||
export function getStargazers(params) {
|
||||
return request({
|
||||
url:
|
||||
"https://api.github.com/repos/chuzhixin/vue-admin-beautiful/stargazers",
|
||||
method: "get",
|
||||
params,
|
||||
timeout: 10000,
|
||||
});
|
||||
}
|
9
src/api/goodsDetail.js
Normal file
@ -0,0 +1,9 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getList(data) {
|
||||
return request({
|
||||
url: "/goodsDetail/getList",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
9
src/api/goodsList.js
Normal file
@ -0,0 +1,9 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getList(data) {
|
||||
return request({
|
||||
url: "/goodsList/getList",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
9
src/api/icon.js
Normal file
@ -0,0 +1,9 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getIconList(data) {
|
||||
return request({
|
||||
url: "/icon/getList",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
25
src/api/menuManagement.js
Normal file
@ -0,0 +1,25 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getTree(data) {
|
||||
return request({
|
||||
url: "/menuManagement/getTree",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function doEdit(data) {
|
||||
return request({
|
||||
url: "/menuManagement/doEdit",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function doDelete(data) {
|
||||
return request({
|
||||
url: "/menuManagement/doDelete",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
8
src/api/notice.js
Normal file
@ -0,0 +1,8 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getNoticeList() {
|
||||
return request({
|
||||
url: "/notice/getList",
|
||||
method: "post",
|
||||
});
|
||||
}
|
25
src/api/personalCenter.js
Normal file
@ -0,0 +1,25 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getList(data) {
|
||||
return request({
|
||||
url: "/personalCenter/getList",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function doEdit(data) {
|
||||
return request({
|
||||
url: "/personalCenter/doEdit",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function doDelete(data) {
|
||||
return request({
|
||||
url: "/personalCenter/doDelete",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
8
src/api/publicKey.js
Normal file
@ -0,0 +1,8 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getPublicKey(data) {
|
||||
return request({
|
||||
url: "/publicKey",
|
||||
method: "post",
|
||||
});
|
||||
}
|
9
src/api/remixIcon.js
Normal file
@ -0,0 +1,9 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getIconList(data) {
|
||||
return request({
|
||||
url: "/remixIcon/getList",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
25
src/api/roleManagement.js
Normal file
@ -0,0 +1,25 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getList(data) {
|
||||
return request({
|
||||
url: "/roleManagement/getList",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function doEdit(data) {
|
||||
return request({
|
||||
url: "/roleManagement/doEdit",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function doDelete(data) {
|
||||
return request({
|
||||
url: "/roleManagement/doDelete",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
9
src/api/router.js
Normal file
@ -0,0 +1,9 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getRouterList(data) {
|
||||
return request({
|
||||
url: "/menu/navigate",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
25
src/api/table.js
Normal file
@ -0,0 +1,25 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getList(data) {
|
||||
return request({
|
||||
url: "/table/getList",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function doEdit(data) {
|
||||
return request({
|
||||
url: "/table/doEdit",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function doDelete(data) {
|
||||
return request({
|
||||
url: "/table/doDelete",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
9
src/api/tree.js
Normal file
@ -0,0 +1,9 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getTreeList(data) {
|
||||
return request({
|
||||
url: "/tree/list",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
37
src/api/user.js
Normal file
@ -0,0 +1,37 @@
|
||||
import request from "@/utils/request";
|
||||
import { encryptedData } from "@/utils/encrypt";
|
||||
import { loginRSA } from "@/config/settings";
|
||||
|
||||
export async function login(data) {
|
||||
if (loginRSA) {
|
||||
data = await encryptedData(data);
|
||||
}
|
||||
return request({
|
||||
url: "/login",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function getInfo(accessToken) {
|
||||
return request({
|
||||
url: "/userInfo",
|
||||
method: "post",
|
||||
data: {
|
||||
accessToken,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
return request({
|
||||
url: "/logout",
|
||||
method: "post",
|
||||
});
|
||||
}
|
||||
export function register() {
|
||||
return request({
|
||||
url: "/register",
|
||||
method: "post",
|
||||
});
|
||||
}
|
25
src/api/userManagement.js
Normal file
@ -0,0 +1,25 @@
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function getList(data) {
|
||||
return request({
|
||||
url: "/userManagement/getList",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function doEdit(data) {
|
||||
return request({
|
||||
url: "/userManagement/doEdit",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function doDelete(data) {
|
||||
return request({
|
||||
url: "/userManagement/doDelete",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
BIN
src/assets/comparison/left.jpg
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
src/assets/comparison/right.jpg
Normal file
After Width: | Height: | Size: 95 KiB |
BIN
src/assets/error_images/401.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
src/assets/error_images/404.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
src/assets/error_images/cloud.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
src/assets/ewm.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
src/assets/login_images/background.jpg
Normal file
After Width: | Height: | Size: 133 KiB |
BIN
src/assets/qr_logo/lqr_logo.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
17
src/colorfulIcon/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
import Vue from "vue";
|
||||
import ColorfullIcon from "@/components/ColorfullIcon";
|
||||
|
||||
Vue.component("vab-colorful-icon", ColorfullIcon);
|
||||
const req = require.context("./svg", false, /\.svg$/),
|
||||
requireAll = (requireContext) => {
|
||||
/*let a = requireContext.keys().map(requireContext);
|
||||
let arr = [];
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
console.log();
|
||||
let icon = a[i].default.id;
|
||||
arr.push(icon);
|
||||
}
|
||||
console.log(JSON.stringify(arr));*/
|
||||
return requireContext.keys().map(requireContext);
|
||||
};
|
||||
requireAll(req);
|
1
src/colorfulIcon/svg/alphabetical_sorting.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg class="icon" width="128" height="128" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M358.4 853.333H245.333l-23.466 64H147.2l121.6-324.266h61.867l119.466 324.266h-68.266l-23.467-64zm-98.133-57.6h81.066l-40.533-121.6-40.533 121.6zm4.266-418.133h162.134v53.333H179.2V390.4L341.333 160H179.2v-53.333h243.2v36.266L264.533 377.6z" fill="#2196F3"/><path d="M810.667 704V106.667h-85.334V704h-128L768 917.333 938.667 704z" fill="#546E7A"/></svg>
|
After Width: | Height: | Size: 463 B |
22
src/colorfulIcon/svg/vab.svg
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg version="1.1" id="Layer_1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="550px" height="400px"
|
||||
xml:space="preserve">
|
||||
<g id="PathID_1" transform="matrix(10.7099, 0, 0, 10.7099, 76.4, 396.15)" opacity="1">
|
||||
<path style="fill: #41b882; fill-opacity: 1;" d="M3.75 -36.65L18.4 -36.65Q22.75 -36.65 24.85 -36.25Q27 -35.9 28.7 -34.75Q30.4 -33.6 31.5 -31.7Q32.65 -29.8 32.65 -27.4Q32.65 -24.85 31.25 -22.7Q29.85 -20.55 27.5 -19.5Q30.85 -18.5 32.65 -16.15Q34.45 -13.8 34.45 -10.6Q34.45 -8.1 33.25 -5.75Q32.1 -3.4 30.1 -1.95Q28.1 -0.55 25.15 -0.25Q23.3 -0.05 16.2 0L3.75 0L3.75 -36.65M11.15 -30.55L11.15 -22.1L16 -22.1Q20.3 -22.1 21.35 -22.2Q23.25 -22.4 24.35 -23.5Q25.45 -24.6 25.45 -26.35Q25.45 -28.05 24.5 -29.1Q23.55 -30.2 21.7 -30.4Q20.6 -30.55 15.4 -30.55L11.15 -30.55M11.15 -16L11.15 -6.2L18 -6.2Q22 -6.2 23.05 -6.4Q24.7 -6.7 25.75 -7.85Q26.8 -9.05 26.8 -11Q26.8 -12.65 26 -13.8Q25.2 -14.95 23.65 -15.45Q22.15 -16 17.1 -16L11.15 -16" />
|
||||
</g>
|
||||
<g id="PathID_2" transform="matrix(10.7099, 0, 0, 10.7099, 76.4, 396.15)" opacity="1">
|
||||
</g>
|
||||
<g id="PathID_3" transform="matrix(5.31826, 0, 0, 2.59618, 172.9, 161.55)" opacity="1">
|
||||
<path style="fill: #35495e; fill-opacity: 1;" d="M3.75 -36.65L17.25 -36.65Q21.8 -36.65 24.2 -35.95Q27.45 -35 29.75 -32.55Q32.05 -30.15 33.25 -26.6Q34.45 -23.1 34.45 -17.95Q34.45 -13.45 33.3 -10.15Q31.95 -6.15 29.4 -3.7Q27.45 -1.8 24.2 -0.75Q21.75 0 17.65 0L3.75 0L3.75 -36.65M11.15 -30.45L11.15 -6.2L16.65 -6.2Q19.75 -6.2 21.1 -6.55Q22.9 -6.95 24.1 -8Q25.3 -9.1 26.05 -11.55Q26.8 -14.05 26.8 -18.3Q26.8 -22.55 26.05 -24.8Q25.3 -27.1 23.95 -28.35Q22.6 -29.65 20.5 -30.1Q18.95 -30.45 14.45 -30.45L11.15 -30.45" />
|
||||
</g>
|
||||
<g id="PathID_4" transform="matrix(5.31826, 0, 0, 2.59618, 172.9, 161.55)" opacity="1">
|
||||
</g>
|
||||
<g id="PathID_5" transform="matrix(5.78477, 0, 0, 3.1825, 171.7, 333.8)" opacity="1">
|
||||
<path style="fill: #35495e; fill-opacity: 1;" d="M3.75 -36.65L17.25 -36.65Q21.8 -36.65 24.2 -35.95Q27.45 -35 29.75 -32.55Q32.05 -30.15 33.25 -26.6Q34.45 -23.1 34.45 -17.95Q34.45 -13.45 33.3 -10.15Q31.95 -6.15 29.4 -3.7Q27.45 -1.8 24.2 -0.75Q21.75 0 17.65 0L3.75 0L3.75 -36.65M11.15 -30.45L11.15 -6.2L16.65 -6.2Q19.75 -6.2 21.1 -6.55Q22.9 -6.95 24.1 -8Q25.3 -9.1 26.05 -11.55Q26.8 -14.05 26.8 -18.3Q26.8 -22.55 26.05 -24.8Q25.3 -27.1 23.95 -28.35Q22.6 -29.65 20.5 -30.1Q18.95 -30.45 14.45 -30.45L11.15 -30.45" />
|
||||
</g>
|
||||
<g id="PathID_6" transform="matrix(5.78477, 0, 0, 3.1825, 171.7, 333.8)" opacity="1">
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
65
src/components/ColorfullIcon/index.vue
Normal file
@ -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: "ColorfulIcon",
|
||||
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>
|
111
src/components/JsonEditor/index.vue
Normal file
@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<div class="json-editor">
|
||||
<label>
|
||||
<textarea ref="textarea" />
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CodeMirror from "codemirror";
|
||||
import "codemirror/addon/lint/lint.css";
|
||||
import "codemirror/lib/codemirror.css";
|
||||
import "codemirror/theme/rubyblue.css";
|
||||
import "codemirror/mode/javascript/javascript";
|
||||
import "codemirror/addon/lint/lint";
|
||||
import "codemirror/addon/lint/json-lint";
|
||||
|
||||
require("script-loader!jsonlint");
|
||||
|
||||
export default {
|
||||
name: "JsonEditor",
|
||||
props: {
|
||||
value: {
|
||||
type: [Array, Object],
|
||||
default: () => {
|
||||
return null;
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
jsonEditor: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
value(value) {
|
||||
const editorValue = this.jsonEditor.getValue();
|
||||
|
||||
if (editorValue) {
|
||||
this.$emit("change", editorValue);
|
||||
} else {
|
||||
this.$baseMessage("JSON不能为空,否则无法生成表格", "error");
|
||||
}
|
||||
if (value !== editorValue) {
|
||||
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2));
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
|
||||
lineNumbers: true,
|
||||
mode: "application/json",
|
||||
gutters: ["CodeMirror-lint-markers"],
|
||||
theme: "rubyblue",
|
||||
lint: true,
|
||||
});
|
||||
|
||||
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2));
|
||||
this.jsonEditor.on("change", (cm) => {
|
||||
if (this.isJsonString(cm.getValue())) {
|
||||
this.$emit("change", cm.getValue());
|
||||
}
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
getValue() {
|
||||
return this.jsonEditor.getValue();
|
||||
},
|
||||
isJsonString(str) {
|
||||
try {
|
||||
if (typeof JSON.parse(str) == "object") {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.json-editor {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.json-editor >>> .CodeMirror {
|
||||
height: auto;
|
||||
min-height: calc(100vh - 220px);
|
||||
}
|
||||
|
||||
.json-editor >>> .CodeMirror-scroll {
|
||||
min-height: calc(100vh - 220px);
|
||||
}
|
||||
|
||||
.json-editor >>> .cm-s-rubyblue span.cm-string {
|
||||
color: #f08047;
|
||||
}
|
||||
|
||||
.json-editor >>> .cm-s-rubyblue .CodeMirror-gutters {
|
||||
padding-right: 10px;
|
||||
|
||||
/* background: transparent; */
|
||||
border-right: 1px solid #fff;
|
||||
}
|
||||
|
||||
.json-editor >>> .cm-s-rubyblue.CodeMirror {
|
||||
/* background: #08233e; */
|
||||
color: white;
|
||||
}
|
||||
</style>
|
69
src/components/RemixIcon/index.vue
Normal file
@ -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: "RemixIcon",
|
||||
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>
|
201
src/components/SelectTree/index.vue
Normal file
@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<div class="select-tree-template">
|
||||
<el-select
|
||||
v-model="selectValue"
|
||||
:clearable="clearable"
|
||||
:collapse-tags="selectType == 'multiple'"
|
||||
:multiple="selectType == 'multiple'"
|
||||
class="vab-tree-select"
|
||||
value-key="id"
|
||||
@clear="clearHandle"
|
||||
@remove-tag="removeTag"
|
||||
>
|
||||
<el-option :value="selectKey">
|
||||
<el-tree
|
||||
id="treeOption"
|
||||
ref="treeOption"
|
||||
:current-node-key="currentNodeKey"
|
||||
:data="treeOptions"
|
||||
:default-checked-keys="defaultSelectedKeys"
|
||||
:default-expanded-keys="defaultSelectedKeys"
|
||||
:highlight-current="true"
|
||||
:props="defaultProps"
|
||||
:show-checkbox="selectType == 'multiple'"
|
||||
node-key="id"
|
||||
@check="checkNode"
|
||||
@node-click="nodeClick"
|
||||
></el-tree>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "SelectTreeTemplate",
|
||||
props: {
|
||||
/* 树形结构数据 */
|
||||
treeOptions: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
/* 单选/多选 */
|
||||
selectType: {
|
||||
type: String,
|
||||
default: () => {
|
||||
return "single";
|
||||
},
|
||||
},
|
||||
/* 初始选中值key */
|
||||
selectedKey: {
|
||||
type: String,
|
||||
default: () => {
|
||||
return "";
|
||||
},
|
||||
},
|
||||
/* 初始选中值name */
|
||||
selectedValue: {
|
||||
type: String,
|
||||
default: () => {
|
||||
return "";
|
||||
},
|
||||
},
|
||||
/* 可做选择的层级 */
|
||||
selectLevel: {
|
||||
type: [String, Number],
|
||||
default: () => {
|
||||
return "";
|
||||
},
|
||||
},
|
||||
/* 可清空选项 */
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: () => {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultProps: {
|
||||
children: "children",
|
||||
label: "name",
|
||||
},
|
||||
defaultSelectedKeys: [], //初始选中值数组
|
||||
currentNodeKey: this.selectedKey,
|
||||
selectValue:
|
||||
this.selectType == "multiple"
|
||||
? this.selectedValue.split(",")
|
||||
: this.selectedValue, //下拉框选中值label
|
||||
selectKey:
|
||||
this.selectType == "multiple"
|
||||
? this.selectedKey.split(",")
|
||||
: this.selectedKey, //下拉框选中值value
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
const that = this;
|
||||
this.initTree();
|
||||
},
|
||||
methods: {
|
||||
// 初始化树的值
|
||||
initTree() {
|
||||
const that = this;
|
||||
if (that.selectedKey) {
|
||||
that.defaultSelectedKeys = that.selectedKey.split(","); // 设置默认展开
|
||||
if (that.selectType == "single") {
|
||||
that.$refs.treeOption.setCurrentKey(that.selectedKey); // 设置默认选中
|
||||
} else {
|
||||
that.$refs.treeOption.setCheckedKeys(that.defaultSelectedKeys);
|
||||
}
|
||||
}
|
||||
},
|
||||
// 清除选中
|
||||
clearHandle() {
|
||||
const that = this;
|
||||
this.selectValue = "";
|
||||
this.selectKey = "";
|
||||
this.defaultSelectedKeys = [];
|
||||
this.currentNodeKey = "";
|
||||
this.clearSelected();
|
||||
if (that.selectType == "single") {
|
||||
that.$refs.treeOption.setCurrentKey(""); // 设置默认选中
|
||||
} else {
|
||||
that.$refs.treeOption.setCheckedKeys([]);
|
||||
}
|
||||
},
|
||||
/* 清空选中样式 */
|
||||
clearSelected() {
|
||||
const allNode = document.querySelectorAll("#treeOption .el-tree-node");
|
||||
allNode.forEach((element) => element.classList.remove("is-current"));
|
||||
},
|
||||
// select多选时移除某项操作
|
||||
removeTag(val) {
|
||||
this.$refs.treeOption.setCheckedKeys([]);
|
||||
},
|
||||
// 点击叶子节点
|
||||
nodeClick(data, node, el) {
|
||||
if (data.rank >= this.selectLevel) {
|
||||
this.selectValue = data.name;
|
||||
this.selectKey = data.id;
|
||||
}
|
||||
},
|
||||
// 节点选中操作
|
||||
checkNode(data, node, el) {
|
||||
const checkedNodes = this.$refs.treeOption.getCheckedNodes();
|
||||
const keyArr = [];
|
||||
const valueArr = [];
|
||||
checkedNodes.forEach((item) => {
|
||||
if (item.rank >= this.selectLevel) {
|
||||
keyArr.push(item.id);
|
||||
valueArr.push(item.name);
|
||||
}
|
||||
});
|
||||
this.selectValue = valueArr;
|
||||
this.selectKey = keyArr;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
|
||||
height: auto;
|
||||
max-height: 274px;
|
||||
padding: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.el-select-dropdown__item.selected {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
ul li > .el-tree .el-tree-node__content {
|
||||
height: auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.el-tree-node__label {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.el-tree > .is-current .el-tree-node__label {
|
||||
font-weight: 700;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.el-tree > .is-current .el-tree-node__children .el-tree-node__label {
|
||||
font-weight: normal;
|
||||
color: #606266;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
/* .vab-tree-select{
|
||||
.el-tag__close.el-icon-close{
|
||||
width:0;
|
||||
overflow:hidden;
|
||||
}
|
||||
} */
|
||||
</style>
|
160
src/components/UploadExcel/index.vue
Normal file
@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<div>
|
||||
<input
|
||||
ref="excel-upload-input"
|
||||
class="excel-upload-input"
|
||||
type="file"
|
||||
accept=".xlsx, .xls"
|
||||
@change="handleClick"
|
||||
/>
|
||||
<div
|
||||
class="drop"
|
||||
@drop="handleDrop"
|
||||
@dragover="handleDragover"
|
||||
@dragenter="handleDragover"
|
||||
>
|
||||
将excel文件拖拽到此处或
|
||||
|
||||
<el-button
|
||||
:loading="loading"
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="handleUpload"
|
||||
>
|
||||
点击上传
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import XLSX from "xlsx";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
beforeUpload: {
|
||||
type: Function,
|
||||
default: () => {},
|
||||
},
|
||||
onSuccess: {
|
||||
type: Function,
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
excelData: {
|
||||
header: null,
|
||||
results: null,
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
generateData({ header, results }) {
|
||||
this.excelData.header = header;
|
||||
this.excelData.results = results;
|
||||
this.onSuccess && this.onSuccess(this.excelData);
|
||||
},
|
||||
handleDrop(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if (this.loading) return;
|
||||
const files = e.dataTransfer.files;
|
||||
if (files.length !== 1) {
|
||||
this.$message.error("只支持上传一个文件!");
|
||||
return;
|
||||
}
|
||||
const rawFile = files[0];
|
||||
|
||||
if (!this.isExcel(rawFile)) {
|
||||
this.$message.error("仅支持上载.xlsx、.xls、.csv后缀文件!");
|
||||
return false;
|
||||
}
|
||||
this.upload(rawFile);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
},
|
||||
handleDragover(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = "复制";
|
||||
},
|
||||
handleUpload() {
|
||||
this.$refs["excel-upload-input"].click();
|
||||
},
|
||||
handleClick(e) {
|
||||
const files = e.target.files;
|
||||
const rawFile = files[0];
|
||||
if (!rawFile) return;
|
||||
this.upload(rawFile);
|
||||
},
|
||||
upload(rawFile) {
|
||||
this.$refs["excel-upload-input"].value = null;
|
||||
|
||||
if (!this.beforeUpload) {
|
||||
this.readerData(rawFile);
|
||||
return;
|
||||
}
|
||||
const before = this.beforeUpload(rawFile);
|
||||
if (before) {
|
||||
this.readerData(rawFile);
|
||||
}
|
||||
},
|
||||
readerData(rawFile) {
|
||||
this.loading = true;
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
const data = e.target.result;
|
||||
const workbook = XLSX.read(data, { type: "array" });
|
||||
const firstSheetName = workbook.SheetNames[0];
|
||||
const worksheet = workbook.Sheets[firstSheetName];
|
||||
const header = this.getHeaderRow(worksheet);
|
||||
const results = XLSX.utils.sheet_to_json(worksheet);
|
||||
this.generateData({ header, results });
|
||||
this.loading = false;
|
||||
resolve();
|
||||
};
|
||||
reader.readAsArrayBuffer(rawFile);
|
||||
});
|
||||
},
|
||||
getHeaderRow(sheet) {
|
||||
const headers = [];
|
||||
const range = XLSX.utils.decode_range(sheet["!ref"]);
|
||||
let C;
|
||||
const R = range.s.r;
|
||||
for (C = range.s.c; C <= range.e.c; ++C) {
|
||||
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })];
|
||||
let hdr = "UNKNOWN " + C;
|
||||
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell);
|
||||
headers.push(hdr);
|
||||
}
|
||||
return headers;
|
||||
},
|
||||
isExcel(file) {
|
||||
return /\.(xlsx|xls|csv)$/.test(file.name);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.excel-upload-input {
|
||||
z-index: -9999;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.drop {
|
||||
position: relative;
|
||||
width: 600px;
|
||||
height: 160px;
|
||||
margin: 0 auto;
|
||||
font-size: 24px;
|
||||
line-height: 160px;
|
||||
color: #bbb;
|
||||
text-align: center;
|
||||
border: 2px dashed #bbb;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
191
src/components/VabCharge/index.vue
Normal file
@ -0,0 +1,191 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<div class="g-container" :style="styleObj">
|
||||
<div class="g-number">
|
||||
<vab-count
|
||||
:start-val="startVal"
|
||||
:end-val="endVal"
|
||||
:duration="duration"
|
||||
:separator="separator"
|
||||
:prefix="prefix"
|
||||
:suffix="suffix"
|
||||
:decimals="decimals"
|
||||
/>
|
||||
</div>
|
||||
<div class="g-contrast">
|
||||
<div class="g-circle"></div>
|
||||
<ul class="g-bubbles">
|
||||
<li v-for="(item, index) in 15" :key="index"></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "VabCharge",
|
||||
props: {
|
||||
styleObj: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
startVal: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
endVal: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
decimals: 2,
|
||||
prefix: "",
|
||||
suffix: "%",
|
||||
separator: ",",
|
||||
duration: 3000,
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
mounted() {},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center; /* 垂直居中 */
|
||||
justify-content: center; /* 水平居中 */
|
||||
width: 100%;
|
||||
background: #000;
|
||||
|
||||
.g-number {
|
||||
position: absolute;
|
||||
top: 27%;
|
||||
z-index: 99;
|
||||
width: 300px;
|
||||
font-size: 32px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.g-container {
|
||||
position: relative;
|
||||
width: 300px;
|
||||
height: 400px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.g-contrast {
|
||||
width: 300px;
|
||||
height: 400px;
|
||||
overflow: hidden;
|
||||
background-color: #000;
|
||||
filter: contrast(15) hue-rotate(0);
|
||||
animation: hueRotate 10s infinite linear;
|
||||
}
|
||||
|
||||
.g-circle {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
filter: blur(8px);
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
content: "";
|
||||
background-color: #00ff6f;
|
||||
border-radius: 42% 38% 62% 49% / 45%;
|
||||
transform: translate(-50%, -50%) rotate(0);
|
||||
animation: rotate 10s infinite linear;
|
||||
}
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
z-index: 99;
|
||||
width: 176px;
|
||||
height: 176px;
|
||||
content: "";
|
||||
background-color: #000;
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.g-bubbles {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
background-color: #00ff6f;
|
||||
filter: blur(5px);
|
||||
border-radius: 100px 100px 0 0;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
li {
|
||||
position: absolute;
|
||||
background: #00ff6f;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@for $i from 0 through 15 {
|
||||
li:nth-child(#{$i}) {
|
||||
$width: 15 + random(15) + px;
|
||||
|
||||
top: 50%;
|
||||
left: 15 + random(70) + px;
|
||||
width: $width;
|
||||
height: $width;
|
||||
transform: translate(-50%, -50%);
|
||||
animation: moveToTop
|
||||
#{random(6) +
|
||||
3}s
|
||||
ease-in-out -#{random(5000) /
|
||||
1000}s
|
||||
infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
50% {
|
||||
border-radius: 45% / 42% 38% 58% 49%;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -50%) rotate(720deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes moveToTop {
|
||||
90% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0.1;
|
||||
transform: translate(-50%, -180px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hueRotate {
|
||||
100% {
|
||||
filter: contrast(15) hue-rotate(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
92
src/components/VabImage/index.vue
Normal file
@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<div class="vab-image__outter">
|
||||
<el-image
|
||||
:src="bigSrc"
|
||||
fit="cover"
|
||||
style="width: 100%; height: 100%;"
|
||||
@click="clickBig"
|
||||
></el-image>
|
||||
<el-image
|
||||
:src="smallSrc"
|
||||
class="vab-image__outter__small"
|
||||
fit="cover"
|
||||
@click="clickSmall"
|
||||
></el-image>
|
||||
<span class="vab-image__outter__percent">{{ percent }}%</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "VabImage",
|
||||
components: {},
|
||||
props: {
|
||||
bigSrc: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
smallSrc: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
percent: {
|
||||
type: Number,
|
||||
default: 97,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
created() {},
|
||||
mounted() {},
|
||||
methods: {
|
||||
clickBig() {
|
||||
this.$emit("clickBig");
|
||||
},
|
||||
clickSmall() {
|
||||
this.$emit("clickSmall");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.vab-image {
|
||||
&__outter {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
::v-deep {
|
||||
img {
|
||||
border-radius: $base-border-radius;
|
||||
}
|
||||
}
|
||||
|
||||
&__small {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 80px;
|
||||
height: 100px;
|
||||
border-bottom: 1px solid $base-color-white;
|
||||
border-left: 1px solid $base-color-white;
|
||||
border-radius: $base-border-radius;
|
||||
}
|
||||
|
||||
&__percent {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: inline-block;
|
||||
min-width: 50px;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
color: $base-color-white;
|
||||
text-align: center;
|
||||
background-color: $base-color-red;
|
||||
border-radius: $base-border-radius;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
313
src/components/VabProfile/index.vue
Normal file
@ -0,0 +1,313 @@
|
||||
<template>
|
||||
<div class="card" :style="styleObj">
|
||||
<div class="card-borders">
|
||||
<div class="border-top"></div>
|
||||
<div class="border-right"></div>
|
||||
<div class="border-bottom"></div>
|
||||
<div class="border-left"></div>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<el-image :src="avatar" class="avatar"></el-image>
|
||||
<div class="username">{{ userName }}</div>
|
||||
<div class="social-icons">
|
||||
<a
|
||||
v-for="(item, index) in iconArray"
|
||||
:key="index"
|
||||
class="social-icon"
|
||||
:href="item.url"
|
||||
target="_blank"
|
||||
>
|
||||
<vab-icon :icon="['fas', item.icon]" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "VabProfile",
|
||||
props: {
|
||||
styleObj: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
userName: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
avatar: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
iconArray: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [
|
||||
{ icon: "bell", url: "" },
|
||||
{ icon: "bookmark", url: "" },
|
||||
{ icon: "cloud-sun", url: "" },
|
||||
];
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
created() {},
|
||||
mounted() {},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card {
|
||||
--card-bg-color: hsl(240, 31%, 25%);
|
||||
--card-bg-color-transparent: hsla(240, 31%, 25%, 0.7);
|
||||
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.card-borders {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.border-top {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background: var(--card-bg-color);
|
||||
transform: translateX(-100%);
|
||||
animation: slide-in-horizontal 0.8s cubic-bezier(0.645, 0.045, 0.355, 1)
|
||||
forwards;
|
||||
}
|
||||
|
||||
.border-right {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
background: var(--card-bg-color);
|
||||
transform: translateY(100%);
|
||||
animation: slide-in-vertical 0.8s cubic-bezier(0.645, 0.045, 0.355, 1)
|
||||
forwards;
|
||||
}
|
||||
|
||||
.border-bottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background: var(--card-bg-color);
|
||||
transform: translateX(100%);
|
||||
animation: slide-in-horizontal-reverse 0.8s
|
||||
cubic-bezier(0.645, 0.045, 0.355, 1) forwards;
|
||||
}
|
||||
|
||||
.border-left {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
background: var(--card-bg-color);
|
||||
transform: translateY(-100%);
|
||||
animation: slide-in-vertical-reverse 0.8s
|
||||
cubic-bezier(0.645, 0.045, 0.355, 1) forwards;
|
||||
}
|
||||
}
|
||||
|
||||
.card-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding: 40px 0 40px 0;
|
||||
background: var(--card-bg-color-transparent);
|
||||
opacity: 0;
|
||||
transform: scale(0.6);
|
||||
animation: bump-in 0.5s 0.8s forwards;
|
||||
|
||||
.avatar {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border: 1px solid $base-color-white;
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
transform: scale(0.6);
|
||||
animation: bump-in 0.5s 1s forwards;
|
||||
}
|
||||
|
||||
.username {
|
||||
position: relative;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 26px;
|
||||
color: transparent;
|
||||
letter-spacing: 2px;
|
||||
animation: fill-text-white 1.2s 2s forwards;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: black;
|
||||
content: "";
|
||||
background: #35b9f1;
|
||||
transform: scaleX(0);
|
||||
transform-origin: left;
|
||||
animation: slide-in-out 1.2s 1.2s cubic-bezier(0.75, 0, 0, 1) forwards;
|
||||
}
|
||||
}
|
||||
|
||||
.social-icons {
|
||||
display: flex;
|
||||
|
||||
.social-icon {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 2.5em;
|
||||
height: 2.5em;
|
||||
margin: 0 15px;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 50%;
|
||||
|
||||
@for $i from 1 through 3 {
|
||||
&:nth-child(#{$i}) {
|
||||
&::before {
|
||||
animation-delay: 2s + 0.1s * $i;
|
||||
}
|
||||
|
||||
&::after {
|
||||
animation-delay: 2.1s + 0.1s * $i;
|
||||
}
|
||||
|
||||
svg {
|
||||
animation-delay: 2.2s + 0.1s * $i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
content: "";
|
||||
border-radius: inherit;
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
&::before {
|
||||
background: #f7f1e3;
|
||||
animation: scale-in 0.5s cubic-bezier(0.75, 0, 0, 1) forwards;
|
||||
}
|
||||
|
||||
&::after {
|
||||
background: #2c3e50;
|
||||
animation: scale-in 0.5s cubic-bezier(0.75, 0, 0, 1) forwards;
|
||||
}
|
||||
|
||||
svg {
|
||||
z-index: 99;
|
||||
transform: scale(0);
|
||||
animation: scale-in 0.5s cubic-bezier(0.75, 0, 0, 1) forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bump-in {
|
||||
50% {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-in-horizontal {
|
||||
50% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-in-horizontal-reverse {
|
||||
50% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-in-vertical {
|
||||
50% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-in-vertical-reverse {
|
||||
50% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-in-out {
|
||||
50% {
|
||||
transform: scaleX(1);
|
||||
transform-origin: left;
|
||||
}
|
||||
|
||||
50.1% {
|
||||
transform-origin: right;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scaleX(0);
|
||||
transform-origin: right;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fill-text-white {
|
||||
to {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scale-in {
|
||||
to {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
</style>
|
44
src/components/VabQrCode/index.vue
Normal file
@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<vue-q-art :config="config"></vue-q-art>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VueQArt from "vue-qart";
|
||||
import qrImg from "@/assets/qr_logo/lqr_logo.png";
|
||||
|
||||
export default {
|
||||
name: "VabQrCode",
|
||||
components: {
|
||||
VueQArt,
|
||||
},
|
||||
props: {
|
||||
imagePath: {
|
||||
type: String,
|
||||
default: qrImg,
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
default: "http://www.boyunvision.com/",
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 500,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
config: {
|
||||
value: this.url,
|
||||
imagePath: this.imagePath,
|
||||
filter: "color",
|
||||
size: this.size,
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
mounted() {},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
20
src/components/VabQueryForm/VabQueryFormBottomPanel.vue
Normal file
@ -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
src/components/VabQueryForm/VabQueryFormLeftPanel.vue
Normal file
@ -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
src/components/VabQueryForm/VabQueryFormRightPanel.vue
Normal file
@ -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
src/components/VabQueryForm/VabQueryFormTopPanel.vue
Normal file
@ -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
src/components/VabQueryForm/index.vue
Normal file
@ -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>
|
124
src/components/VabQuill/index.vue
Normal file
@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<div class="vab-quill" :class="classes">
|
||||
<div ref="editor" :style="styles"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Quill from "quill";
|
||||
import "quill/dist/quill.core.css";
|
||||
import "quill/dist/quill.snow.css";
|
||||
import "quill/dist/quill.bubble.css";
|
||||
|
||||
export default {
|
||||
name: "VabQuill",
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
minHeight: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
Quill: null,
|
||||
currentValue: "",
|
||||
options: {
|
||||
theme: "snow",
|
||||
bounds: document.body,
|
||||
debug: "warn",
|
||||
modules: {
|
||||
toolbar: [
|
||||
["bold", "italic", "underline", "strike"],
|
||||
[{ header: [1, 2, 3, 4, 5, 6, false] }],
|
||||
[{ size: ["small", false, "large", "huge"] }],
|
||||
[{ color: [] }, { background: [] }],
|
||||
["blockquote", "code-block"],
|
||||
[{ list: "ordered" }, { list: "bullet" }],
|
||||
[{ indent: "-1" }, { indent: "+1" }],
|
||||
[{ align: [] }],
|
||||
[{ direction: "rtl" }],
|
||||
["clean"],
|
||||
["link", "image"],
|
||||
],
|
||||
},
|
||||
placeholder: "内容...",
|
||||
readOnly: false,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes() {
|
||||
return [
|
||||
{
|
||||
"vab-quill-no-border": !this.border,
|
||||
},
|
||||
];
|
||||
},
|
||||
styles() {
|
||||
let style = {};
|
||||
if (this.minHeight) {
|
||||
style.minHeight = `${this.minHeight}px`;
|
||||
}
|
||||
if (this.height) {
|
||||
style.height = `${this.height}px`;
|
||||
}
|
||||
return style;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
if (val !== this.currentValue) {
|
||||
this.currentValue = val;
|
||||
if (this.Quill) {
|
||||
this.Quill.pasteHTML(this.value);
|
||||
}
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.Quill = null;
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
const editor = this.$refs.editor;
|
||||
this.Quill = new Quill(editor, this.options);
|
||||
this.Quill.pasteHTML(this.currentValue);
|
||||
this.Quill.on("text-change", (delta, oldDelta, source) => {
|
||||
const html = this.$refs.editor.children[0].innerHTML;
|
||||
const text = this.Quill.getText();
|
||||
const quill = this.Quill;
|
||||
this.currentValue = html;
|
||||
this.$emit("input", html);
|
||||
this.$emit("on-change", { html, text, quill });
|
||||
});
|
||||
this.Quill.on("text-change", (delta, oldDelta, source) => {
|
||||
this.$emit("on-text-change", delta, oldDelta, source);
|
||||
});
|
||||
this.Quill.on("selection-change", (range, oldRange, source) => {
|
||||
this.$emit("on-selection-change", range, oldRange, source);
|
||||
});
|
||||
this.Quill.on("editor-change", (eventName, ...args) => {
|
||||
this.$emit("on-editor-change", eventName, ...args);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
81
src/components/VabSnow/index.vue
Normal file
@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<div class="content" :style="styleObj">
|
||||
<div v-for="(item, index) in 200" :key="index" class="snow"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "VabSnow",
|
||||
props: {
|
||||
styleObj: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
created() {},
|
||||
mounted() {},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background: radial-gradient(ellipse at bottom, #1b2735 0%, #090a0f 100%);
|
||||
filter: drop-shadow(0 0 10px white);
|
||||
}
|
||||
|
||||
@function random_range($min, $max) {
|
||||
$rand: random();
|
||||
$random_range: $min + floor($rand * (($max - $min) + 1));
|
||||
|
||||
@return $random_range;
|
||||
}
|
||||
|
||||
.snow {
|
||||
$total: 200;
|
||||
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
|
||||
@for $i from 1 through $total {
|
||||
$random-x: random(1000000) * 0.0001vw;
|
||||
$random-offset: random_range(-100000, 100000) * 0.0001vw;
|
||||
$random-x-end: $random-x + $random-offset;
|
||||
$random-x-end-yoyo: $random-x + ($random-offset / 2);
|
||||
$random-yoyo-time: random_range(30000, 80000) / 100000;
|
||||
$random-yoyo-y: $random-yoyo-time * 100vh;
|
||||
$random-scale: random(10000) * 0.0001;
|
||||
$fall-duration: random_range(10, 30) * 1s;
|
||||
$fall-delay: random(30) * -1s;
|
||||
|
||||
&:nth-child(#{$i}) {
|
||||
opacity: random(10000) * 0.0001;
|
||||
transform: translate($random-x, -10px) scale($random-scale);
|
||||
animation: fall-#{$i} $fall-duration $fall-delay linear infinite;
|
||||
}
|
||||
|
||||
@keyframes fall-#{$i} {
|
||||
#{percentage($random-yoyo-time)} {
|
||||
transform: translate($random-x-end, $random-yoyo-y) scale($random-scale);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate($random-x-end-yoyo, 100vh) scale($random-scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
95
src/components/VabSticky/index.vue
Normal file
@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<div :style="{ height: height + 'px', zIndex: zIndex }">
|
||||
<div
|
||||
:class="className"
|
||||
:style="{
|
||||
top: isSticky ? stickyTop + 'px' : '',
|
||||
zIndex: zIndex,
|
||||
position: position,
|
||||
width: width,
|
||||
height: height + 'px',
|
||||
}"
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "VabSticky",
|
||||
props: {
|
||||
stickyTop: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
zIndex: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
className: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
active: false,
|
||||
position: "",
|
||||
width: undefined,
|
||||
height: undefined,
|
||||
isSticky: false,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.height = this.$el.getBoundingClientRect().height;
|
||||
window.addEventListener("scroll", this.handleScroll);
|
||||
window.addEventListener("resize", this.handleResize);
|
||||
},
|
||||
activated() {
|
||||
this.handleScroll();
|
||||
},
|
||||
destroyed() {
|
||||
window.removeEventListener("scroll", this.handleScroll);
|
||||
window.removeEventListener("resize", this.handleResize);
|
||||
},
|
||||
methods: {
|
||||
sticky() {
|
||||
if (this.active) {
|
||||
return;
|
||||
}
|
||||
this.position = "fixed";
|
||||
this.active = true;
|
||||
this.width = this.width + "px";
|
||||
this.isSticky = true;
|
||||
},
|
||||
handleReset() {
|
||||
if (!this.active) {
|
||||
return;
|
||||
}
|
||||
this.reset();
|
||||
},
|
||||
reset() {
|
||||
this.position = "";
|
||||
this.width = "auto";
|
||||
this.active = false;
|
||||
this.isSticky = false;
|
||||
},
|
||||
handleScroll() {
|
||||
const width = this.$el.getBoundingClientRect().width;
|
||||
this.width = width || "auto";
|
||||
const offsetTop = this.$el.getBoundingClientRect().top;
|
||||
if (offsetTop < this.stickyTop) {
|
||||
this.sticky();
|
||||
return;
|
||||
}
|
||||
this.handleReset();
|
||||
},
|
||||
handleResize() {
|
||||
if (this.isSticky) {
|
||||
this.width = this.$el.getBoundingClientRect().width + "px";
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
267
src/components/VabUpload/index.vue
Normal file
@ -0,0 +1,267 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
:visible.sync="dialogFormVisible"
|
||||
width="909px"
|
||||
:before-close="handleClose"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div class="upload">
|
||||
<el-alert
|
||||
:closable="false"
|
||||
:title="`支持jpg、jpeg、png格式,单次可最多选择${limit}张图片,每张不可大于${size}M,如果大于${size}M会自动为您过滤`"
|
||||
type="info"
|
||||
>
|
||||
</el-alert>
|
||||
<br />
|
||||
<el-upload
|
||||
ref="upload"
|
||||
class="upload-content"
|
||||
:name="name"
|
||||
:data="data"
|
||||
:action="action"
|
||||
:headers="headers"
|
||||
:on-change="handleChange"
|
||||
:on-preview="handlePreview"
|
||||
:on-remove="handleRemove"
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="handleSuccess"
|
||||
:on-progress="handleProgress"
|
||||
:on-error="handleError"
|
||||
:file-list="fileList"
|
||||
:multiple="true"
|
||||
:auto-upload="false"
|
||||
accept="image/png, image/jpeg"
|
||||
:limit="limit"
|
||||
list-type="picture-card"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<i slot="trigger" class="el-icon-plus"></i>
|
||||
<el-dialog
|
||||
title="查看大图"
|
||||
append-to-body
|
||||
:visible.sync="dialogVisible"
|
||||
>
|
||||
<div style="padding-bottom: 20px !important;">
|
||||
<img width="100%" :src="dialogImageUrl" alt="" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
</el-upload>
|
||||
</div>
|
||||
<div
|
||||
slot="footer"
|
||||
class="dialog-footer"
|
||||
style="position: relative; padding-right: 15px; text-align: right;"
|
||||
>
|
||||
<div
|
||||
v-if="show"
|
||||
style="position: absolute; top: 10px; left: 15px; color: #999;"
|
||||
>
|
||||
正在上传中... 当前上传成功数:{{ imgSuccessNum }}张 当前上传失败数:{{
|
||||
imgErrorNum
|
||||
}}张
|
||||
</div>
|
||||
<el-button type="primary" @click="handleClose">关闭</el-button>
|
||||
<el-button
|
||||
style="margin-left: 10px;"
|
||||
size="small"
|
||||
type="success"
|
||||
:loading="loading"
|
||||
@click="submitUpload"
|
||||
>开始上传
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { tokenName } from "@/config/settings";
|
||||
|
||||
export default {
|
||||
name: "VabUpload",
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
default: "/upload",
|
||||
required: true,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: "file",
|
||||
required: true,
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 50,
|
||||
required: true,
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
loading: false,
|
||||
dialogVisible: false,
|
||||
dialogImageUrl: "",
|
||||
action: "",
|
||||
headers: {},
|
||||
fileList: [],
|
||||
picture: "picture",
|
||||
imgNum: 0,
|
||||
imgSuccessNum: 0,
|
||||
imgErrorNum: 0,
|
||||
typeList: null,
|
||||
title: "上传",
|
||||
dialogFormVisible: false,
|
||||
data: {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
percentage() {
|
||||
if (this.allImgNum == 0) return 0;
|
||||
return this.$baseLodash.round(this.imgNum / this.allImgNum, 2) * 100;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
if ("development" === process.env.NODE_ENV) {
|
||||
this.api = process.env.VUE_APP_BASE_API;
|
||||
} else {
|
||||
this.api = `${window.location.protocol}//${window.location.host}`;
|
||||
}
|
||||
|
||||
this.action = this.api + this.url;
|
||||
this.headers[tokenName] = this.$baseAccessToken();
|
||||
},
|
||||
methods: {
|
||||
submitUpload() {
|
||||
this.$refs.upload.submit();
|
||||
},
|
||||
handleProgress(event, file, fileList) {
|
||||
this.loading = true;
|
||||
this.show = true;
|
||||
},
|
||||
handleChange(file, fileList) {
|
||||
if (file.size > 1048576 * this.size) {
|
||||
fileList.map((item, index) => {
|
||||
if (item === file) {
|
||||
fileList.splice(index, 1);
|
||||
}
|
||||
});
|
||||
this.fileList = fileList;
|
||||
} else {
|
||||
this.allImgNum = fileList.length;
|
||||
}
|
||||
},
|
||||
handleSuccess(response, file, fileList) {
|
||||
this.imgNum = this.imgNum + 1;
|
||||
this.imgSuccessNum = this.imgSuccessNum + 1;
|
||||
if (fileList.length === this.imgNum) {
|
||||
setTimeout(() => {
|
||||
this.$emit("fetchDatas");
|
||||
this.$baseMessage(
|
||||
`上传完成! 共上传${fileList.length}张图片`,
|
||||
"success"
|
||||
);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.loading = false;
|
||||
this.show = false;
|
||||
}, 1000);
|
||||
},
|
||||
handleError(err, file, fileList) {
|
||||
this.imgNum = this.imgNum + 1;
|
||||
this.imgErrorNum = this.imgErrorNum + 1;
|
||||
this.$baseMessage(
|
||||
`文件[${file.raw.name}]上传失败,文件大小为${this.$baseLodash.round(
|
||||
file.raw.size / 1024,
|
||||
0
|
||||
)}KB`,
|
||||
"error"
|
||||
);
|
||||
setTimeout(() => {
|
||||
this.loading = false;
|
||||
this.show = false;
|
||||
}, 1000);
|
||||
},
|
||||
handleRemove(file, fileList) {
|
||||
this.imgNum = this.imgNum - 1;
|
||||
this.allNum = this.allNum - 1;
|
||||
},
|
||||
handlePreview(file) {
|
||||
this.dialogImageUrl = file.url;
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
handleExceed(files, fileList) {
|
||||
this.$baseMessage(
|
||||
`当前限制选择 ${this.limit} 个文件,本次选择了
|
||||
${files.length}
|
||||
个文件`,
|
||||
"error"
|
||||
);
|
||||
},
|
||||
handleShow(data) {
|
||||
this.title = "上传";
|
||||
this.data = data;
|
||||
this.dialogFormVisible = true;
|
||||
},
|
||||
handleClose() {
|
||||
this.fileList = [];
|
||||
this.picture = "picture";
|
||||
this.allImgNum = 0;
|
||||
this.imgNum = 0;
|
||||
this.imgSuccessNum = 0;
|
||||
this.imgErrorNum = 0;
|
||||
if ("development" === process.env.NODE_ENV) {
|
||||
this.api = process.env.VUE_APP_BASE_API;
|
||||
} else {
|
||||
this.api = `${window.location.protocol}//${window.location.host}`;
|
||||
}
|
||||
|
||||
this.action = this.api + this.url;
|
||||
this.headers[tokenName] = this.$baseAccessToken();
|
||||
this.dialogFormVisible = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.upload {
|
||||
height: 600px;
|
||||
|
||||
.upload-content {
|
||||
.el-upload__tip {
|
||||
display: block;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
::v-deep {
|
||||
.el-upload--picture-card {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
margin: 3px 8px 8px 8px;
|
||||
border: 2px dashed #c0ccda;
|
||||
}
|
||||
|
||||
.el-upload-list--picture {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.el-upload-list--picture-card {
|
||||
.el-upload-list__item {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
margin: 3px 8px 8px 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
85
src/config/permission.js
Normal file
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @copyright chuzhixin 1204505056@qq.com
|
||||
* @description 路由守卫,目前两种模式:all模式与intelligence模式
|
||||
*/
|
||||
import router from "@/router";
|
||||
import store from "@/store";
|
||||
import VabProgress from "nprogress";
|
||||
import "nprogress/nprogress.css";
|
||||
import getPageTitle from "@/utils/pageTitle";
|
||||
import {
|
||||
authentication,
|
||||
loginInterception,
|
||||
routesWhiteList,
|
||||
progressBar,
|
||||
recordRoute,
|
||||
} from "./settings";
|
||||
|
||||
VabProgress.configure({
|
||||
easing: "ease",
|
||||
speed: 500,
|
||||
trickleSpeed: 200,
|
||||
showSpinner: false,
|
||||
});
|
||||
router.beforeResolve(async (to, from, next) => {
|
||||
if (progressBar) VabProgress.start();
|
||||
let hasToken = store.getters["user/accessToken"];
|
||||
|
||||
if (!loginInterception) hasToken = true;
|
||||
|
||||
if (hasToken) {
|
||||
if (to.path === "/login") {
|
||||
next({ path: "/" });
|
||||
if (progressBar) VabProgress.done();
|
||||
} else {
|
||||
const hasPermissions =
|
||||
store.getters["user/permissions"] &&
|
||||
store.getters["user/permissions"].length > 0;
|
||||
if (hasPermissions) {
|
||||
next();
|
||||
} else {
|
||||
try {
|
||||
let permissions;
|
||||
if (!loginInterception) {
|
||||
//settings.js loginInterception为false时,创建虚拟权限
|
||||
store.dispatch("user/setPermissions", ["admin"]);
|
||||
permissions = ["admin"];
|
||||
} else {
|
||||
permissions = await store.dispatch("user/getInfo");
|
||||
}
|
||||
|
||||
let accessRoutes = [];
|
||||
if (authentication === "intelligence") {
|
||||
accessRoutes = await store.dispatch(
|
||||
"routes/setRoutes",
|
||||
permissions
|
||||
);
|
||||
} else if (authentication === "all") {
|
||||
accessRoutes = await store.dispatch("routes/setAllRoutes");
|
||||
}
|
||||
router.addRoutes(accessRoutes);
|
||||
next({ ...to, replace: true });
|
||||
} catch {
|
||||
await store.dispatch("user/resetAccessToken");
|
||||
if (progressBar) VabProgress.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (routesWhiteList.indexOf(to.path) !== -1) {
|
||||
next();
|
||||
} else {
|
||||
if (recordRoute) {
|
||||
next(`/login?redirect=${to.path}`);
|
||||
} else {
|
||||
next("/login");
|
||||
}
|
||||
|
||||
if (progressBar) VabProgress.done();
|
||||
}
|
||||
}
|
||||
document.title = getPageTitle(to.meta.title);
|
||||
});
|
||||
router.afterEach(() => {
|
||||
if (progressBar) VabProgress.done();
|
||||
});
|
99
src/config/settings.js
Normal file
@ -0,0 +1,99 @@
|
||||
/**
|
||||
* @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" || process.env.NODE_ENV === "preview"
|
||||
? "vab-mock-server"
|
||||
: "http://your.website.com",
|
||||
//标题 (包括初次加载雪花屏的标题 页面的标题 浏览器的标题)
|
||||
title: "vue-admin-beautiful",
|
||||
//简写
|
||||
abbreviation: "vab",
|
||||
//开发环境端口号
|
||||
devPort: "80",
|
||||
//版本号
|
||||
version: process.env.VUE_APP_VERSION,
|
||||
//烦请保留package.json作者信息 保留版权可免费商用 如需去除并自定义为自己企业的版权请联系群主QQ 1204505056 需支付299元 恶意修改发生纠纷及出现任何问题 由修改人自行承担
|
||||
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加密
|
||||
loginRSA: 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,
|
||||
//代码生成机生成在view下的文件夹名称
|
||||
templateFolder: "project",
|
||||
};
|
77
src/directive/drag/drag.js
Normal file
@ -0,0 +1,77 @@
|
||||
export default {
|
||||
bind(el, binding, vnode) {
|
||||
if (
|
||||
el.querySelector(".el-dialog__header") &&
|
||||
el.querySelector(".el-dialog")
|
||||
) {
|
||||
const dialogHeaderEl = el.querySelector(".el-dialog__header");
|
||||
const dragDom = el.querySelector(".el-dialog");
|
||||
dialogHeaderEl.style.cssText += ";cursor:move;";
|
||||
dragDom.style.cssText += ";top:0;";
|
||||
|
||||
const getStyle = (function () {
|
||||
if (window.document.currentStyle) {
|
||||
return (dom, attr) => dom.currentStyle[attr];
|
||||
} else {
|
||||
return (dom, attr) => getComputedStyle(dom, false)[attr];
|
||||
}
|
||||
})();
|
||||
|
||||
dialogHeaderEl.onmousedown = (e) => {
|
||||
const disX = e.clientX - dialogHeaderEl.offsetLeft;
|
||||
const disY = e.clientY - dialogHeaderEl.offsetTop;
|
||||
|
||||
const dragDomWidth = dragDom.offsetWidth;
|
||||
const dragDomHeight = dragDom.offsetHeight;
|
||||
|
||||
const screenWidth = document.body.clientWidth;
|
||||
const screenHeight = document.body.clientHeight;
|
||||
|
||||
const minDragDomLeft = dragDom.offsetLeft;
|
||||
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
|
||||
|
||||
const minDragDomTop = dragDom.offsetTop;
|
||||
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight;
|
||||
|
||||
let styL = getStyle(dragDom, "left");
|
||||
let styT = getStyle(dragDom, "top");
|
||||
|
||||
if (styL.includes("%")) {
|
||||
styL = +document.body.clientWidth * (+styL / 100);
|
||||
styT = +document.body.clientHeight * (+styT / 100);
|
||||
} else {
|
||||
styL = +styL.replace(/\px/g, "");
|
||||
styT = +styT.replace(/\px/g, "");
|
||||
}
|
||||
|
||||
document.onmousemove = function (e) {
|
||||
let left = e.clientX - disX;
|
||||
let top = e.clientY - disY;
|
||||
|
||||
if (-left > minDragDomLeft) {
|
||||
left = -minDragDomLeft;
|
||||
} else if (left > maxDragDomLeft) {
|
||||
left = maxDragDomLeft;
|
||||
}
|
||||
|
||||
if (-top > minDragDomTop) {
|
||||
top = -minDragDomTop;
|
||||
} else if (top > maxDragDomTop) {
|
||||
top = maxDragDomTop;
|
||||
}
|
||||
|
||||
dragDom.style.cssText += `;left:${left + styL}px;top:${
|
||||
top + styT
|
||||
}px;`;
|
||||
|
||||
vnode.child.$emit("dragDialog");
|
||||
};
|
||||
|
||||
document.onmouseup = function (e) {
|
||||
document.onmousemove = null;
|
||||
document.onmouseup = null;
|
||||
};
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|