Commit f88c3868 by chuzhixin

🎉🎉🎉仓库重置到2020年9月29日,Vue2.6最后一个版本,之前版本不再支持,具体请查阅文档,Vue 3.0版本即将发布请耐心等待!!!

parents
> 1%
last 2 versions
not dead
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
src/assets
src/icons
public
dist
node_modules
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,
},
},
],
};
*.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
patreon: chuzhixin
---
name: 问题提问(不按规范提问不解答)
about: 详细描述你的问题
title: ''
labels: ''
assignees: ''
---
#### 出现的问题
#### 操作了什么以后出现了的
#### 详细的报错截图、控制台截图
#### 是否已经百度过了、是否已经努力尝试解决了
.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
/zx-templates
/package-lock.json
module.exports = {
extends: ["stylelint-config-recess-order", "stylelint-config-prettier"],
};
{
"[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,
"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.stylelint": true,
"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,
"prettier.htmlWhitespaceSensitivity": "ignore",
"prettier.vueIndentScriptAndStyle": true,
"docthis.authorName": "chuzhixin 1204505056@qq.com",
"docthis.includeAuthorTag": true,
"docthis.includeDescriptionTag": true,
"docthis.enableHungarianNotationEvaluation": true,
"docthis.inferTypesFromNames": true,
"vetur.format.defaultFormatter.html": "prettier"
}
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.
<div align="center"><img width="200" src="https://gitee.com/chu1204505056/vue-admin-beautiful/raw/master/src/colorfulIcon/svg/vab.svg"/>
<h1> vue-admin-beautiful </h1>
<h3>一款基于 vue+element-ui 的绝佳的通用型、中后台前端框架</h3>
<h3>An excellent general-purpose, middle and background front-end framework based on Vue + element UI</h3>
</div>
[![](https://img.shields.io/github/stars/chuzhixin/vue-admin-beautiful?style=flat-square&label=Stars&logo=github)
](https://github.com/chuzhixin/vue-admin-beautiful)
## 演示地址
### - [🚀 演示地址:vue-admin-beautiful (横向纵向布局无缝切换)](https://chu1204505056.gitee.io/vue-admin-beautiful/?hmsr=%E6%8F%92%E4%BB%B6%E5%B8%82%E5%9C%BA&hmpl=&hmcu=&hmkw=&hmci=)
### - [🚀 vue-admin-beautiful-pro 版演示地址](https://chu1204505056.gitee.io/vue-admin-beautiful-pro/?hmsr=%E6%8F%92%E4%BB%B6%E5%B8%82%E5%9C%BA&hmpl=&hmcu=&hmkw=&hmci=)
### - [🚀 vue-admin-beautiful-mini vue3.0 预览版地址](https://chu1204505056.gitee.io/vue-admin-beautiful-mini/?hmsr=%E6%8F%92%E4%BB%B6%E5%B8%82%E5%9C%BA&hmpl=&hmcu=&hmkw=&hmci=)
## vue-admin-beautiful 前端讨论群-1 972435319
不管您加或者不加,您都可以享受到开源的代码,感谢您的支持和信任,群内提供 vue-admin-beautiful-template 基础版本和详细的基础使用文档适合框架快速入门
![img](https://chu1204505056.gitee.io/vabBooks/img/ewm.png)
## 安装
```bash
# 克隆项目
git clone https://github.com/chuzhixin/vue-admin-beautiful.git
# 进入项目目录
npm vue-admin-beautiful
# 安装依赖
npm i
# 本地开发 启动项目
cnpm run serve
```
#### github 标星增长量统计
[![Stargazers over time](https://starcharts.herokuapp.com/chuzhixin/vue-admin-beautiful.svg)](https://github.com/chuzhixin/vue-admin-beautiful)
#### 开发者评级
[![chuzhixin's github stats](https://github-readme-stats.vercel.app/api?username=chuzhixin)](https://github.com/chuzhixin/vue-admin-beautiful)
#
<div align="center"><img width="200" src="https://gitee.com/chu1204505056/vue-admin-beautiful/raw/master/src/colorfulIcon/svg/vab.svg"/>
<h1> vue-admin-beautiful </h1>
<h3>一款基于 vue+element-ui 的绝佳的通用型、中后台前端框架</h3>
<h3>An excellent general-purpose, middle and background front-end framework based on Vue + element UI</h3>
</div>
![image](https://repository-images.githubusercontent.com/249342059/8ff9d000-bef5-11ea-837f-8c265b79e3db)
## vue-admin-beautiful 前端讨论群-1 972435319
不管您加或者不加,您都可以享受到开源的代码,感谢您的支持和信任,群内提供 vue-admin-beautiful-template 基础版本和详细的基础使用文档适合框架快速入门
![img](https://gitee.com/chu1204505056/vabBooks/raw/gh-pages/img/ewm.png)
## 🎉🎉🎉 基于 vue3.0 的 vue-admin-beautiful-mini 正在快马加鞭的开发,敬请期待!!!
## 地址
### - [🎉 演示地址 1:vue-admin-beautiful](http://beautiful.panm.cn/vue-admin-beautiful/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
### - [🎉 演示地址 2:vue-admin-beautiful](https://chu1204505056.gitee.io/vue-admin-beautiful/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
### - [🚀 pro 版演示地址 1:vue-admin-beautiful-pro](http://beautiful.panm.cn/vue-admin-beautiful-pro/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
### - [🚀 pro 版演示地址 2:vue-admin-beautiful-pro](https://chu1204505056.gitee.io/vue-admin-beautiful-pro/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
### - [🌐 github 仓库地址](https://github.com/chuzhixin/vue-admin-beautiful/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
### - [🌐 码云仓库地址](https://gitee.com/chu1204505056/vue-admin-beautiful/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
### - [🌐 vue3.0 版本研发进度展示(基础版本已全部贯通、适配电脑、手机、平板)](https://chu1204505056.gitee.io/vue-admin-beautiful-mini/?hmsr=github&hmpl=&hmcu=&hmkw=&hmci=)
## 安装
```bash
# 克隆项目
git clone https://github.com/chuzhixin/vue-admin-beautiful.git
# 进入项目目录
cd vue-admin-beautiful
# 安装依赖
npm i
# 本地开发 启动项目
npm run serve
```
## install
```bash
# Clone project
git clone https://github.com/chuzhixin/vue-admin-beautiful.git
# Enter project directory
cd vue-admin-beautiful
# Installation dependency
npm i
# Start project
npm run serve
```
## 友情链接
### - [uView 文档(超棒的移动跨端框架,文档详细,上手容易)](https://uviewui.com/)
### - [Element UI 表单设计及代码生成器(可视化表单设计器,一键生成 element 表单)](https://github.com/JakHuang/form-generator/)
### - [luch-request(基于 Promise 开发的 uni-app 跨平台、项目级别的请求库,它有更小的体积,易用的 api,方便简单的自定义能力)](https://www.quanzhan.co/luch-request/)
### - [umyui 文档(开发者准备的基于 Vue 2.0 的桌面端组件库; 流畅渲染表格万级数据)](http://www.umyui.com/)
## setting.js 配置
- 说明:这里有好多你会用到的配置项。
- 位置:src/config/settings.js
- 注意:此处可能不是最新代码具体可查看[github 最新的 settings.js 配置](https://github.com/chuzhixin/vue-admin-beautiful/blob/master/src/config/settings.js)
- 示例代码:
```js
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 全局变量配置
*/
module.exports = {
// 开发以及部署时的URL
publicPath: "",
// 生产环境构建文件的目录名
outputDir: "dist",
// 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。
assetsDir: "static",
// 开发环境每次保存时是否输出为eslint编译警告
lintOnSave: true,
// 进行编译的依赖
transpileDependencies: ["vue-echarts", "resize-detector", "zx-layouts"],
// 默认的接口地址 如果是开发环境和生产环境走vab-mock-server,当然你也可以选择自己配置成需要的接口地址
baseURL:
process.env.NODE_ENV === "development"
? "vab-mock-server"
: "vab-mock-server",
//标题 (包括初次加载雪花屏的标题 页面的标题 浏览器的标题)
title: "vue-admin-beautiful",
//简写
abbreviation: "vab",
//开发环境端口号
devPort: "80",
//版本号
version: process.env.VUE_APP_VERSION,
//烦请保留package.json作者信息 保留版权可免费商用
copyright: process.env.VUE_APP_AUTHOR,
//是否显示页面底部版权信息,建议您显示,当然您也可以选择不显示,不管您是付费用户还是未付费用户您都有选择显示或者不显示的权利
footerCopyright: process.env.NODE_ENV !== "development" ? true : false,
//是否显示右上角github图标
githubCorner: process.env.NODE_ENV !== "development" ? true : false,
//是否显示顶部进度条
progressBar: true,
//缓存路由的最大数量
keepAliveMaxNum: 99,
// 路由模式,可选值为 history 或 hash
routerMode: "hash",
//不经过token校验的路由
routesWhiteList: ["/login", "/register", "/404", "/401"],
//加载时显示文字
loadingText: "正在加载中...",
//token名称
tokenName: "accessToken",
//token在localStorage、sessionStorage、cookie存储的key的名称
tokenTableName: "vue-admin-beautiful",
//token存储位置localStorage sessionStorage cookie
storage: "localStorage",
//token失效回退到登录页时是否记录本次的路由
recordRoute: true,
//是否显示logo,不显示时设置false,显示时请填写remixIcon图标名称,暂时只支持设置remixIcon
logo: "vuejs-fill",
//是否国定头部 固定fixed 不固定noFixed
header: "fixed",
//横纵布局 horizontal vertical
layout: "vertical",
//是否开启主题配置按钮
themeBar: true,
//是否显示多标签页
tagsBar: true,
//是否显示骨架屏
skeleton: false,
//配后端数据的接收方式application/json;charset=UTF-8或者application/x-www-form-urlencoded;charset=UTF-8
contentType: "application/json;charset=UTF-8",
//消息框消失时间
messageDuration: 3000,
//最长请求时间
requestTimeout: 5000,
//操作正常code
successCode: 200,
//登录失效code
invalidCode: 402,
//无权限code
noPermissionCode: 401,
//是否显示在页面高亮错误
errorLog: ["development", "test", "production"],
//是否开启登录拦截
loginInterception: true,
//是否开启登录RSA加密
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
## 捐赠
![img](https://chu1204505056.gitee.io/vabBooks/img/donation.png)
#### github 标星增长量统计
[![Stargazers over time](https://starcharts.herokuapp.com/chuzhixin/vue-admin-beautiful.svg)](https://github.com/chuzhixin/vue-admin-beautiful)
#### 开发者评级
[![chuzhixin's github stats](https://github-readme-stats.vercel.app/api?username=chuzhixin)](https://github.com/chuzhixin/vue-admin-beautiful)
## 关于框架的声明
框架在保留作者版权信息的前提下可免费用于商业使用,框架所有代码包含 npm 包中的源码内容均为免费开放,如果您愿意支持我、或者希望完全变成自己的版权信息,需支付 299 元,如果您愿意加入 VIP 群学习需支付 100 元,这一切都是在您自愿的基础上,如果您觉得框架一文不值,请直接略过,高抬贵手放我一马,不要恶意刷差评,希望每个使用 vue-admin-beautiful 的人无论过程怎样,结局都是美好的,联系方式 QQ 1204505056
## vue-admin-beautiful 前端讨论群-2 1139183756
不管您加或者不加,您都可以享受到开源的代码,感谢您的支持和信任,群内提供 vue-admin-beautiful-template 基础版本和详细的基础使用文档适合框架快速入门
![img](https://gitee.com/chu1204505056/vabBooks/raw/gh-pages/img/ewm_2.png)
# 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.
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"],
};
#!/usr/bin/env bash
set -e
npm run build
cd dist
touch .nojekyll
git init
git add -A
git commit -m '🎉🎉🎉仓库重置到2020年9月29日,Vue2.6最后一个版本,之前版本不再支持,具体请查阅文档,Vue 3.0版本请耐心等待!!!'
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
###/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
###
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.
const data = [
{
title: "vue-admin-beautiful-pro beta版本已发布,点我提前体验",
url: "https://chu1204505056.gitee.io/vue-admin-beautiful-pro/#/index",
},
];
module.exports = [
{
url: "/ad/getList",
type: "get",
response() {
return {
code: 200,
msg: "success",
data,
};
},
},
];
const data = [
{
name: "奉/fendou飘逸的梦",
qq: "812770127",
excuse: "上来就开骂,不可原谅",
},
{
name: "江荻",
qq: "2324945654",
excuse: "上来就开骂,不可原谅",
},
{
name: "Diamond",
qq: "494904935",
excuse: "跟我道歉可以选择原谅",
},
{
name: "Mr、无涯",
qq: "2198457489",
excuse: "已原谅",
},
{
name: "玩世不恭丶江小白",
qq: "1779263221",
excuse: "睁眼说瞎话",
},
{
name: "福州客家网络科技有限公司(潘芳林等兄弟二人)",
qq: "1409198410、1778486252",
excuse:
"剽窃、破解框架授权并发布到网上还伪装成善人,公开道歉并尊重我的劳动成果可以选择原谅",
},
{
name: "willina",
qq: "405522648",
excuse:
"上来就开骂道:You and your git submit are just a rubbish,不可原谅",
},
{
name: "7(赵海鹏)",
qq: "252334666",
excuse: "欺骗两个善良的小姑娘,做完项目不付70%的尾款,强烈抵制",
},
{
name: "生活,一半记忆.一半继续",
qq: "252667193",
excuse: "30多岁,不学无术,造谣抹黑,不可原谅",
},
{
name: "AIRLOO",
qq: "5971794",
excuse: "已原谅",
},
{
name: "master Z",
qq: "1832819123",
excuse: "不尊重别人的劳动成果,认为开源就得无偿替他服务,不可原谅",
},
{
name: "想象中。。。",
qq: "329492979",
excuse: "不尊重别人的劳动成果,认为开源就得无偿替他服务,不可原谅",
},
{
name: "苏潍—菏泽微智科技",
qq: "328580081",
excuse: "无言以对",
},
{
name: "罗阳",
qq: "1320168680",
excuse: "不尊重别人的劳动成果,认为开源就得无偿替他服务,不可原谅",
},
];
module.exports = [
{
url: "/blacklist/getList",
type: "post",
response() {
return {
code: 200,
msg: "success",
data,
};
},
},
];
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",
},
{
content: "修改zx-layouts引入方式",
timestamp: "2020-07-15",
},
{
content:
"记录这一天vue-admin-beautiful在插件市场、百度已花费超过1万元广告费用,希望一切都值得",
timestamp: "2020-07-18",
},
{
content: "主题配置添加海洋之心、绿荫草场、荣耀典藏、暗黑之子模式",
timestamp: "2020-07-18",
},
{
content: "全局axios请求全面支持Status Code拦截处理",
timestamp: "2020-07-29",
},
{
content: "重构全局loadding加载代码",
timestamp: "2020-07-31",
},
{
content: "升级stylelint自动排序功能",
timestamp: "2020-08-25",
},
{
content: "修复视频播放器组件重载路由失效的bug",
timestamp: "2020-09-03",
},
{
content: "修复极个别情况image-loader打包报错",
timestamp: "2020-09-18",
},
{
content: "全网首个基于vue3.0开发的admin框架已发布,具体请访问github",
timestamp: "2020-09-22",
},
];
module.exports = [
{
url: "/changeLog/getList",
type: "post",
response() {
return {
code: 200,
msg: "success",
totalCount: 999,
data: data,
};
},
},
];
const data = [
"alphabetical_sorting",
"advance",
"address_book",
"alphabetical_sorting",
"advertising",
"alarm_clock",
"area_chart",
"approval",
"answers",
"approve",
"assistant",
"audio_file",
"automotive",
"automatic",
"bad_decision",
"bar_chart",
"bearish",
"biomass",
"biohazard",
"binoculars",
"bookmark",
"briefcase",
"biotech",
"broken_link",
"business",
"bullish",
"business_contact",
"businesswoman",
"cable_release",
"calculator",
"businessman",
"calendar",
"butting_in",
"call_transfer",
"callback",
"camcorder",
"camera",
"camcorder_pro",
"cancel",
"camera_addon",
"camera_identificatio",
"capacitor",
"candle_sticks",
"checkmark",
"circuit",
"charge_battery",
"clear_filters",
"clapperboard",
"clock",
"close_up_mode",
"collaboration",
"cell_phone",
"collapse",
"collect",
"cloth",
"combo_chart",
"comments",
"conference_call",
"compact_camera",
"contacts",
"copyleft",
"copyright",
"crystal_oscillator",
"cursor",
"currency_exchange",
"customer_support",
"dam",
"data_backup",
"data_configuration",
"data_encryption",
"data_protection",
"data_recovery",
"database",
"data_sheet",
"debt",
"decision",
"delete_column",
"delete_database",
"department",
"delete_row",
"deployment",
"dislike",
"disapprove",
"disclaimer",
"display",
"document",
"do_not_insert",
"do_not_mix",
"do_not_inhale",
"donate",
"down",
"doughnut_chart",
"down_left",
"down_right",
"download",
"edit_image",
"electrical_sensor",
"electrical_threshold",
"electricity",
"electro_devices",
"electronics",
"empty_battery",
"empty_filter",
"empty_trash",
"end_call",
"engineering",
"entering_heaven_aliv",
"expand",
"export",
"expired",
"factory",
"factory_breakdown",
"external",
"faq",
"feed_in",
"file",
"feedback",
"film",
"filled_filter",
"filing_cabinet",
"film_reel",
"flash_auto",
"fine_print",
"flash_off",
"flash_on",
"flow_chart",
"folder",
"frame",
"full_battery",
"full_trash",
"gallery",
"generic_sorting_asc",
"generic_sorting_desc",
"genealogy",
"globe",
"good_decision",
"headset",
"grid",
"graduation_cap",
"heat_map",
"high_priority",
"high_battery",
"image_file",
"home",
"idea",
"import",
"in_transit",
"integrated_webcam",
"inspection",
"invite",
"internal",
"ipad",
"info",
"iphone",
"kindle",
"key",
"landscape",
"left",
"left_down",
"left_up",
"leave",
"like_placeholder",
"light_at_the_end_of_",
"library",
"line_chart",
"link",
"like",
"lock",
"list",
"lock_landscape",
"low_battery",
"lock_portrait",
"low_priority",
"make_decision",
"medium_priority",
"manager",
"menu",
"middle_battery",
"minus",
"missed_call",
"mind_map",
"mms",
"multiple_cameras",
"money_transfer",
"music",
"multiple_devices",
"multiple_smartphones",
"multiple_inputs",
"negative_dynamic",
"neutral_decision",
"night_landscape",
"news",
"neutral_trading",
"night_portrait",
"no_idea",
"next",
"no_video",
"nook",
"ok",
"org_unit",
"opened_folder",
"old_time_camera",
"online_support",
"organization",
"package",
"paid",
"parallel_tasks",
"overtime",
"panorama",
"phone",
"phone_android",
"photo_reel",
"pie_chart",
"picture",
"planner",
"plus",
"podium_with_audience",
"podium_without_speak",
"podium_with_speaker",
"previous",
"portrait_mode",
"positive_dynamic",
"privacy",
"process",
"puzzle",
"questions",
"print",
"radar_plot",
"rating",
"ratings",
"reading",
"redo",
"reading_ebook",
"refresh",
"registered_trademark",
"right",
"reuse",
"remove_image",
"right_down",
"right_up",
"rotate_to_portrait",
"rules",
"rotate_camera",
"rotate_to_landscape",
"ruler",
"scatter_plot",
"search",
"safe",
"self_service_kiosk",
"selfie",
"serial_tasks",
"sales_performance",
"settings",
"services",
"share",
"shipped",
"sim_card",
"shop",
"service_mark",
"sim_card_chip",
"signature",
"smartphone_tablet",
"sound_recording_copy",
"sms",
"speaker",
"slr_back_side",
"start",
"stack_of_photos",
"statistics",
"sports_mode",
"support",
"synchronize",
"switch_camera",
"survey",
"tablet_android",
"template",
"trademark",
"todo_list",
"touchscreen_smartpho",
"timeline",
"tree_structure",
"undo",
"up_left",
"two_smartphones",
"unlock",
"up",
"up_right",
"upload",
"video_call",
"video_file",
"view_details",
"video_projector",
"vip",
"voice_presentation",
"webcam",
"voicemail",
"workflow",
"about",
"accept_database",
"add_image",
"add_column",
"add_database",
"add_row",
];
module.exports = [
{
url: "/colorfulIcon/getList",
type: "post",
response(config) {
const { title, pageNo = 1, pageSize = 72 } = config.body;
let mockList = data.filter((item) => {
if (title && item.indexOf(title) < 0) return false;
return true;
});
const pageList = mockList.filter(
(item, index) =>
index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
);
return {
code: 200,
msg: "success",
totalCount: mockList.length,
data: pageList,
};
},
},
];
const { mock } = require("mockjs");
module.exports = [
{
url: "/goodsDetail/getList",
type: "post",
response(config) {
return {
code: 200,
msg: "success",
totalCount: 999,
data: mock({
"data|10": [
{
id: "@id",
},
],
}).data,
};
},
},
{
url: "/goodsDetail/doEdit",
type: "post",
response(config) {
return {
code: 200,
msg: "模拟保存成功",
};
},
},
{
url: "/goodsDetail/doDelete",
type: "post",
response(config) {
return {
code: 200,
msg: "模拟删除成功",
};
},
},
];
const { mock } = require("mockjs");
const List = [];
const count = 999;
let num = 0;
for (let i = 0; i < count; i++) {
List.push(
mock({
uuid: "@uuid",
image: `https://picsum.photos/300/600?random=${num++}`,
title: "@ctitle",
description: "@csentence",
link: "https://www.baidu.com",
price: "@integer(100, 500)",
"status|1": [1, 0],
"isRecommend|1": [1, 0],
})
);
}
module.exports = [
{
url: "/goodsList/getList",
type: "post",
response(config) {
const { title = "", pageNo = 1, pageSize = 20 } = config.body;
let mockList = List.filter((item) => {
if (title && item.title.indexOf(title) < 0) return false;
return true;
});
const pageList = mockList.filter(
(item, index) =>
index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
);
return {
code: 200,
msg: "success",
totalCount: count,
data: pageList,
};
},
},
];
const data = [
"ad",
"address-book",
"address-card",
"adjust",
"air-freshener",
"align-center",
"align-justify",
"align-left",
"align-right",
"allergies",
"ambulance",
"american-sign-language-interpreting",
"anchor",
"angle-double-down",
"angle-double-left",
"angle-double-right",
"angle-double-up",
"angle-down",
"angle-left",
"angle-right",
"angle-up",
"angry",
"ankh",
"apple-alt",
"archive",
"archway",
"arrow-alt-circle-down",
"arrow-alt-circle-left",
"arrow-alt-circle-right",
"arrow-alt-circle-up",
"arrow-circle-down",
"arrow-circle-left",
"arrow-circle-right",
"arrow-circle-up",
"arrow-down",
"arrow-left",
"arrow-right",
"arrow-up",
"arrows-alt",
"arrows-alt-h",
"arrows-alt-v",
"assistive-listening-systems",
"asterisk",
"at",
"atlas",
"atom",
"audio-description",
"award",
"baby",
"baby-carriage",
"backspace",
"backward",
"bacon",
"bahai",
"balance-scale",
"balance-scale-left",
"balance-scale-right",
"ban",
"band-aid",
"barcode",
"bars",
"baseball-ball",
"basketball-ball",
"bath",
"battery-empty",
"battery-full",
"battery-half",
"battery-quarter",
"battery-three-quarters",
"bed",
"beer",
"bell",
"bell-slash",
"bezier-curve",
"bible",
"bicycle",
"biking",
"binoculars",
"biohazard",
"birthday-cake",
"blender",
"blender-phone",
"blind",
"blog",
"bold",
"bolt",
"bomb",
"bone",
"bong",
"book",
"book-dead",
"book-medical",
"book-open",
"book-reader",
"bookmark",
"border-all",
"border-none",
"border-style",
"bowling-ball",
"box",
"box-open",
"boxes",
"braille",
"brain",
"bread-slice",
"briefcase",
"briefcase-medical",
"broadcast-tower",
"broom",
"brush",
"bug",
"building",
"bullhorn",
"bullseye",
"burn",
"bus",
"bus-alt",
"business-time",
"calculator",
"calendar",
"calendar-alt",
"calendar-check",
"calendar-day",
"calendar-minus",
"calendar-plus",
"calendar-times",
"calendar-week",
"camera",
"camera-retro",
"campground",
"candy-cane",
"cannabis",
"capsules",
"car",
"car-alt",
"car-battery",
"car-crash",
"car-side",
"caravan",
"caret-down",
"caret-left",
"caret-right",
"caret-square-down",
"caret-square-left",
"caret-square-right",
"caret-square-up",
"caret-up",
"carrot",
"cart-arrow-down",
"cart-plus",
"cash-register",
"cat",
"certificate",
"chair",
"chalkboard",
"chalkboard-teacher",
"charging-station",
"chart-area",
"chart-bar",
"chart-line",
"chart-pie",
"check",
"check-circle",
"check-double",
"check-square",
"cheese",
"chess",
"chess-bishop",
"chess-board",
"chess-king",
"chess-knight",
"chess-pawn",
"chess-queen",
"chess-rook",
"chevron-circle-down",
"chevron-circle-left",
"chevron-circle-right",
"chevron-circle-up",
"chevron-down",
"chevron-left",
"chevron-right",
"chevron-up",
"child",
"church",
"circle",
"circle-notch",
"city",
"clinic-medical",
"clipboard",
"clipboard-check",
"clipboard-list",
"clock",
"clone",
"closed-captioning",
"cloud",
"cloud-download-alt",
"cloud-meatball",
"cloud-moon",
"cloud-moon-rain",
"cloud-rain",
"cloud-showers-heavy",
"cloud-sun",
"cloud-sun-rain",
"cloud-upload-alt",
"cocktail",
"code",
"code-branch",
"coffee",
"cog",
"cogs",
"coins",
"columns",
"comment",
"comment-alt",
"comment-dollar",
"comment-dots",
"comment-medical",
"comment-slash",
"comments",
"comments-dollar",
"compact-disc",
"compass",
"compress",
"compress-alt",
"compress-arrows-alt",
"concierge-bell",
"cookie",
"cookie-bite",
"copy",
"copyright",
"couch",
"credit-card",
"crop",
"crop-alt",
"cross",
"crosshairs",
"crow",
"crown",
"crutch",
"cube",
"cubes",
"cut",
"database",
"deaf",
"democrat",
"desktop",
"dharmachakra",
"diagnoses",
"dice",
"dice-d20",
"dice-d6",
"dice-five",
"dice-four",
"dice-one",
"dice-six",
"dice-three",
"dice-two",
"digital-tachograph",
"directions",
"divide",
"dizzy",
"dna",
"dog",
"dollar-sign",
"dolly",
"dolly-flatbed",
"donate",
"door-closed",
"door-open",
"dot-circle",
"dove",
"download",
"drafting-compass",
"dragon",
"draw-polygon",
"drum",
"drum-steelpan",
"drumstick-bite",
"dumbbell",
"dumpster",
"dumpster-fire",
"dungeon",
"edit",
"egg",
"eject",
"ellipsis-h",
"ellipsis-v",
"envelope",
"envelope-open",
"envelope-open-text",
"envelope-square",
"equals",
"eraser",
"ethernet",
"euro-sign",
"exchange-alt",
"exclamation",
"exclamation-circle",
"exclamation-triangle",
"expand",
"expand-alt",
"expand-arrows-alt",
"external-link-alt",
"external-link-square-alt",
"eye",
"eye-dropper",
"eye-slash",
"fan",
"fast-backward",
"fast-forward",
"fax",
"feather",
"feather-alt",
"female",
"fighter-jet",
"file",
"file-alt",
"file-archive",
"file-audio",
"file-code",
"file-contract",
"file-csv",
"file-download",
"file-excel",
"file-export",
"file-image",
"file-import",
"file-invoice",
"file-invoice-dollar",
"file-medical",
"file-medical-alt",
"file-pdf",
"file-powerpoint",
"file-prescription",
"file-signature",
"file-upload",
"file-video",
"file-word",
"fill",
"fill-drip",
"film",
"filter",
"fingerprint",
"fire",
"fire-alt",
"fire-extinguisher",
"first-aid",
"fish",
"fist-raised",
"flag",
"flag-checkered",
"flag-usa",
"flask",
"flushed",
"folder",
"folder-minus",
"folder-open",
"folder-plus",
"font",
"football-ball",
"forward",
"frog",
"frown",
"frown-open",
"funnel-dollar",
"futbol",
"gamepad",
"gas-pump",
"gavel",
"gem",
"genderless",
"ghost",
"gift",
"gifts",
"glass-cheers",
"glass-martini",
"glass-martini-alt",
"glass-whiskey",
"glasses",
"globe",
"globe-africa",
"globe-americas",
"globe-asia",
"globe-europe",
"golf-ball",
"gopuram",
"graduation-cap",
"greater-than",
"greater-than-equal",
"grimace",
"grin",
"grin-alt",
"grin-beam",
"grin-beam-sweat",
"grin-hearts",
"grin-squint",
"grin-squint-tears",
"grin-stars",
"grin-tears",
"grin-tongue",
"grin-tongue-squint",
"grin-tongue-wink",
"grin-wink",
"grip-horizontal",
"grip-lines",
"grip-lines-vertical",
"grip-vertical",
"guitar",
"h-square",
"hamburger",
"hammer",
"hamsa",
"hand-holding",
"hand-holding-heart",
"hand-holding-usd",
"hand-lizard",
"hand-middle-finger",
"hand-paper",
"hand-peace",
"hand-point-down",
"hand-point-left",
"hand-point-right",
"hand-point-up",
"hand-pointer",
"hand-rock",
"hand-scissors",
"hand-spock",
"hands",
"hands-helping",
"handshake",
"hanukiah",
"hard-hat",
"hashtag",
"hat-cowboy",
"hat-cowboy-side",
"hat-wizard",
"hdd",
"heading",
"headphones",
"headphones-alt",
"headset",
"heart",
"heart-broken",
"heartbeat",
"helicopter",
"highlighter",
"hiking",
"hippo",
"history",
"hockey-puck",
"holly-berry",
"home",
"horse",
"horse-head",
"hospital",
"hospital-alt",
"hospital-symbol",
"hot-tub",
"hotdog",
"hotel",
"hourglass",
"hourglass-end",
"hourglass-half",
"hourglass-start",
"house-damage",
"hryvnia",
"i-cursor",
"ice-cream",
"icicles",
"icons",
"id-badge",
"id-card",
"id-card-alt",
"igloo",
"image",
"images",
"inbox",
"indent",
"industry",
"infinity",
"info",
"info-circle",
"italic",
"jedi",
"joint",
"journal-whills",
"kaaba",
"key",
"keyboard",
"khanda",
"kiss",
"kiss-beam",
"kiss-wink-heart",
"kiwi-bird",
"landmark",
"language",
"laptop",
"laptop-code",
"laptop-medical",
"laugh",
"laugh-beam",
"laugh-squint",
"laugh-wink",
"layer-group",
"leaf",
"lemon",
"less-than",
"less-than-equal",
"level-down-alt",
"level-up-alt",
"life-ring",
"lightbulb",
"link",
"lira-sign",
"list",
"list-alt",
"list-ol",
"list-ul",
"location-arrow",
"lock",
"lock-open",
"long-arrow-alt-down",
"long-arrow-alt-left",
"long-arrow-alt-right",
"long-arrow-alt-up",
"low-vision",
"luggage-cart",
"magic",
"magnet",
"mail-bulk",
"male",
"map",
"map-marked",
"map-marked-alt",
"map-marker",
"map-marker-alt",
"map-pin",
"map-signs",
"marker",
"mars",
"mars-double",
"mars-stroke",
"mars-stroke-h",
"mars-stroke-v",
"mask",
"medal",
"medkit",
"meh",
"meh-blank",
"meh-rolling-eyes",
"memory",
"menorah",
"mercury",
"meteor",
"microchip",
"microphone",
"microphone-alt",
"microphone-alt-slash",
"microphone-slash",
"microscope",
"minus",
"minus-circle",
"minus-square",
"mitten",
"mobile",
"mobile-alt",
"money-bill",
"money-bill-alt",
"money-bill-wave",
"money-bill-wave-alt",
"money-check",
"money-check-alt",
"monument",
"moon",
"mortar-pestle",
"mosque",
"motorcycle",
"mountain",
"mouse",
"mouse-pointer",
"mug-hot",
"music",
"network-wired",
"neuter",
"newspaper",
"not-equal",
"notes-medical",
"object-group",
"object-ungroup",
"oil-can",
"om",
"otter",
"outdent",
"pager",
"paint-brush",
"paint-roller",
"palette",
"pallet",
"paper-plane",
"paperclip",
"parachute-box",
"paragraph",
"parking",
"passport",
"pastafarianism",
"paste",
"pause",
"pause-circle",
"paw",
"peace",
"pen",
"pen-alt",
"pen-fancy",
"pen-nib",
"pen-square",
"pencil-alt",
"pencil-ruler",
"people-carry",
"pepper-hot",
"percent",
"percentage",
"person-booth",
"phone",
"phone-alt",
"phone-slash",
"phone-square",
"phone-square-alt",
"phone-volume",
"photo-video",
"piggy-bank",
"pills",
"pizza-slice",
"place-of-worship",
"plane",
"plane-arrival",
"plane-departure",
"play",
"play-circle",
"plug",
"plus",
"plus-circle",
"plus-square",
"podcast",
"poll",
"poll-h",
"poo",
"poo-storm",
"poop",
"portrait",
"pound-sign",
"power-off",
"pray",
"praying-hands",
"prescription",
"prescription-bottle",
"prescription-bottle-alt",
"print",
"procedures",
"project-diagram",
"puzzle-piece",
"qrcode",
"question",
"question-circle",
"quidditch",
"quote-left",
"quote-right",
"quran",
"radiation",
"radiation-alt",
"rainbow",
"random",
"receipt",
"record-vinyl",
"recycle",
"redo",
"redo-alt",
"registered",
"remove-format",
"reply",
"reply-all",
"republican",
"restroom",
"retweet",
"ribbon",
"ring",
"road",
"robot",
"rocket",
"route",
"rss",
"rss-square",
"ruble-sign",
"ruler",
"ruler-combined",
"ruler-horizontal",
"ruler-vertical",
"running",
"rupee-sign",
"sad-cry",
"sad-tear",
"satellite",
"satellite-dish",
"save",
"school",
"screwdriver",
"scroll",
"sd-card",
"search",
"search-dollar",
"search-location",
"search-minus",
"search-plus",
"seedling",
"server",
"shapes",
"share",
"share-alt",
"share-alt-square",
"share-square",
"shekel-sign",
"shield-alt",
"ship",
"shipping-fast",
"shoe-prints",
"shopping-bag",
"shopping-basket",
"shopping-cart",
"shower",
"shuttle-van",
"sign",
"sign-in-alt",
"sign-language",
"sign-out-alt",
"signal",
"signature",
"sim-card",
"sitemap",
"skating",
"skiing",
"skiing-nordic",
"skull",
"skull-crossbones",
"slash",
"sleigh",
"sliders-h",
"smile",
"smile-beam",
"smile-wink",
"smog",
"smoking",
"smoking-ban",
"sms",
"snowboarding",
"snowflake",
"snowman",
"snowplow",
"socks",
"solar-panel",
"sort",
"sort-alpha-down",
"sort-alpha-down-alt",
"sort-alpha-up",
"sort-alpha-up-alt",
"sort-amount-down",
"sort-amount-down-alt",
"sort-amount-up",
"sort-amount-up-alt",
"sort-down",
"sort-numeric-down",
"sort-numeric-down-alt",
"sort-numeric-up",
"sort-numeric-up-alt",
"sort-up",
"spa",
"space-shuttle",
"spell-check",
"spider",
"spinner",
"splotch",
"spray-can",
"square",
"square-full",
"square-root-alt",
"stamp",
"star",
"star-and-crescent",
"star-half",
"star-half-alt",
"star-of-david",
"star-of-life",
"step-backward",
"step-forward",
"stethoscope",
"sticky-note",
"stop",
"stop-circle",
"stopwatch",
"store",
"store-alt",
"stream",
"street-view",
"strikethrough",
"stroopwafel",
"subscript",
"subway",
"suitcase",
"suitcase-rolling",
"sun",
"superscript",
"surprise",
"swatchbook",
"swimmer",
"swimming-pool",
"synagogue",
"sync",
"sync-alt",
"syringe",
"table",
"table-tennis",
"tablet",
"tablet-alt",
"tablets",
"tachometer-alt",
"tag",
"tags",
"tape",
"tasks",
"taxi",
"teeth",
"teeth-open",
"temperature-high",
"temperature-low",
"tenge",
"terminal",
"text-height",
"text-width",
"th",
"th-large",
"th-list",
"theater-masks",
"thermometer",
"thermometer-empty",
"thermometer-full",
"thermometer-half",
"thermometer-quarter",
"thermometer-three-quarters",
"thumbs-down",
"thumbs-up",
"thumbtack",
"ticket-alt",
"times",
"times-circle",
"tint",
"tint-slash",
"tired",
"toggle-off",
"toggle-on",
"toilet",
"toilet-paper",
"toolbox",
"tools",
"tooth",
"torah",
"torii-gate",
"tractor",
"trademark",
"traffic-light",
"trailer",
"train",
"tram",
"transgender",
"transgender-alt",
"trash",
"trash-alt",
"trash-restore",
"trash-restore-alt",
"tree",
"trophy",
"truck",
"truck-loading",
"truck-monster",
"truck-moving",
"truck-pickup",
"tshirt",
"tty",
"tv",
"umbrella",
"umbrella-beach",
"underline",
"undo",
"undo-alt",
"universal-access",
"university",
"unlink",
"unlock",
"unlock-alt",
"upload",
"user",
"user-alt",
"user-alt-slash",
"user-astronaut",
"user-check",
"user-circle",
"user-clock",
"user-cog",
"user-edit",
"user-friends",
"user-graduate",
"user-injured",
"user-lock",
"user-md",
"user-minus",
"user-ninja",
"user-nurse",
"user-plus",
"user-secret",
"user-shield",
"user-slash",
"user-tag",
"user-tie",
"user-times",
"users",
"users-cog",
"utensil-spoon",
"utensils",
"vector-square",
"venus",
"venus-double",
"venus-mars",
"vial",
"vials",
"video",
"video-slash",
"vihara",
"voicemail",
"volleyball-ball",
"volume-down",
"volume-mute",
"volume-off",
"volume-up",
"vote-yea",
"vr-cardboard",
"walking",
"wallet",
"warehouse",
"water",
"wave-square",
"weight",
"weight-hanging",
"wheelchair",
"wifi",
"wind",
"window-close",
"window-maximize",
"window-minimize",
"window-restore",
"wine-bottle",
"wine-glass",
"wine-glass-alt",
"won-sign",
"wrench",
"x-ray",
"yen-sign",
"yin-yang",
];
module.exports = [
{
url: "/icon/getList",
type: "post",
response(config) {
const { title, pageNo = 1, pageSize = 72 } = config.body;
let mockList = data.filter((item) => {
if (title && item.indexOf(title) < 0) return false;
return true;
});
const pageList = mockList.filter(
(item, index) =>
index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
);
return {
code: 200,
msg: "success",
totalCount: mockList.length,
data: pageList,
};
},
},
];
module.exports = [
{
url: "/menuManagement/getTree",
type: "post",
response(config) {
return {
code: 200,
msg: "success",
totalCount: 999,
data: [
{
id: "root",
label: "全部角色",
children: [
{
id: "@id",
permission: "admin",
label: "admin角色",
},
{
id: "@id",
permission: "editor",
label: "editor角色",
},
],
},
],
};
},
},
{
url: "/menuManagement/doEdit",
type: "post",
response(config) {
return {
code: 200,
msg: "模拟保存成功",
};
},
},
{
url: "/menuManagement/doDelete",
type: "post",
response(config) {
return {
code: 200,
msg: "模拟删除成功",
};
},
},
];
const data = [
{
title: "究竟是什么样的终点,才配得上这一路的颠沛流离。。。",
closable: false,
type: "success",
},
{
title:
"作者寄语:感谢Star,感恩相遇,愿世间美好与我们环环相扣,加油!屏幕前的我们,打破桎梏,坚守初心。其实人生改变命运的机会并没有太多,我们并不是不优秀,我们也并不是一无是处,我们也希望驻足山巅被众人仰望,也许我们缺少的只是一个机会,缺少的只是生命中的导师,我希望这个框架帮助到更多的人,希望有一天,我们面试的时候不再胆怯,希望有一天别人看到的不仅仅是你的努力,还有你的功成名就,出人头地。",
closable: false,
type: "warning",
},
{
title:
"鸣谢:尤雨溪、蒋豪群、element-ui、唐金州、花裤衩、贤心、iView、uView的开源项目给我带来的很多的灵感,弱小的人才习惯嘲讽与否定,内心强大的人从不吝啬赞美与鼓励,人生在世,得到每个人的认可几乎是痴心妄想,我也只是一条略懂前端的咸鱼,可我仍一直怀揣着改变世界的梦想,希望我们每个人,不管过程怎样,结局都是美好的。",
closable: false,
type: "success",
},
{
title:
"随笔:我一直在寻找开源的真谛,我一直再想什么是开源,我一开始觉得免费就是开源,好像又不是。我理解的开源是:你也开源,我也开源,大家一起贡献,相互帮助。我最担心的事情是:我一个小人物,去伺候一众的伸手党,我想,这不是开源该有的氛围。我还太年轻,不懂什么是格局,我只知道,无私的帮助他人,能给我带来快乐,却不能给我带来收入,当然,有时候,快乐对我来说就已经足够了。可惜我是一个人,没有精力帮助到每一个人,可惜这个世界需要赚钱,才能过上平凡的生活,可惜了我的梦想,这个物欲横流的时代,理想主义的我们,即使内心坚决如铁,也似乎寸步难行。",
closable: false,
type: "success",
},
];
module.exports = [
{
url: "/notice/getList",
type: "post",
response() {
return {
code: 200,
msg: "success",
data,
};
},
},
];
const { mock } = require("mockjs");
module.exports = [
{
url: "/personalCenter/getList",
type: "post",
response(config) {
return {
code: 200,
msg: "success",
totalCount: 999,
data: mock({
"data|10": [
{
id: "@id",
},
],
}).data,
};
},
},
{
url: "/personalCenter/doEdit",
type: "post",
response(config) {
return {
code: 200,
msg: "模拟保存成功",
};
},
},
{
url: "/personalCenter/doDelete",
type: "post",
response(config) {
return {
code: 200,
msg: "模拟删除成功",
};
},
},
];
const data = [
"24-hours-fill",
"24-hours-line",
"4k-fill",
"4k-line",
"a-b",
"account-box-fill",
"account-box-line",
"account-circle-fill",
"account-circle-line",
"account-pin-box-fill",
"account-pin-box-line",
"account-pin-circle-fill",
"account-pin-circle-line",
"add-box-fill",
"add-box-line",
"add-circle-fill",
"add-circle-line",
"add-fill",
"add-line",
"admin-fill",
"admin-line",
"advertisement-fill",
"advertisement-line",
"airplay-fill",
"airplay-line",
"alarm-fill",
"alarm-line",
"alarm-warning-fill",
"alarm-warning-line",
"album-fill",
"album-line",
"alert-fill",
"alert-line",
"aliens-fill",
"aliens-line",
"align-bottom",
"align-center",
"align-justify",
"align-left",
"align-right",
"align-top",
"align-vertically",
"alipay-fill",
"alipay-line",
"amazon-fill",
"amazon-line",
"anchor-fill",
"anchor-line",
"ancient-gate-fill",
"ancient-gate-line",
"ancient-pavilion-fill",
"ancient-pavilion-line",
"android-fill",
"android-line",
"angularjs-fill",
"angularjs-line",
"anticlockwise-2-fill",
"anticlockwise-2-line",
"anticlockwise-fill",
"anticlockwise-line",
"app-store-fill",
"app-store-line",
"apple-fill",
"apple-line",
"apps-2-fill",
"apps-2-line",
"apps-fill",
"apps-line",
"archive-drawer-fill",
"archive-drawer-line",
"archive-fill",
"archive-line",
"arrow-down-circle-fill",
"arrow-down-circle-line",
"arrow-down-fill",
"arrow-down-line",
"arrow-down-s-fill",
"arrow-down-s-line",
"arrow-drop-down-fill",
"arrow-drop-down-line",
"arrow-drop-left-fill",
"arrow-drop-left-line",
"arrow-drop-right-fill",
"arrow-drop-right-line",
"arrow-drop-up-fill",
"arrow-drop-up-line",
"arrow-go-back-fill",
"arrow-go-back-line",
"arrow-go-forward-fill",
"arrow-go-forward-line",
"arrow-left-circle-fill",
"arrow-left-circle-line",
"arrow-left-down-fill",
"arrow-left-down-line",
"arrow-left-fill",
"arrow-left-line",
"arrow-left-right-fill",
"arrow-left-right-line",
"arrow-left-s-fill",
"arrow-left-s-line",
"arrow-left-up-fill",
"arrow-left-up-line",
"arrow-right-circle-fill",
"arrow-right-circle-line",
"arrow-right-down-fill",
"arrow-right-down-line",
"arrow-right-fill",
"arrow-right-line",
"arrow-right-s-fill",
"arrow-right-s-line",
"arrow-right-up-fill",
"arrow-right-up-line",
"arrow-up-circle-fill",
"arrow-up-circle-line",
"arrow-up-down-fill",
"arrow-up-down-line",
"arrow-up-fill",
"arrow-up-line",
"arrow-up-s-fill",
"arrow-up-s-line",
"artboard-2-fill",
"artboard-2-line",
"artboard-fill",
"artboard-line",
"article-fill",
"article-line",
"aspect-ratio-fill",
"aspect-ratio-line",
"asterisk",
"at-fill",
"at-line",
"attachment-2",
"attachment-fill",
"attachment-line",
"auction-fill",
"auction-line",
"award-fill",
"award-line",
"baidu-fill",
"baidu-line",
"ball-pen-fill",
"ball-pen-line",
"bank-card-2-fill",
"bank-card-2-line",
"bank-card-fill",
"bank-card-line",
"bank-fill",
"bank-line",
"bar-chart-2-fill",
"bar-chart-2-line",
"bar-chart-box-fill",
"bar-chart-box-line",
"bar-chart-fill",
"bar-chart-grouped-fill",
"bar-chart-grouped-line",
"bar-chart-horizontal-fill",
"bar-chart-horizontal-line",
"bar-chart-line",
"barcode-box-fill",
"barcode-box-line",
"barcode-fill",
"barcode-line",
"barricade-fill",
"barricade-line",
"base-station-fill",
"base-station-line",
"basketball-fill",
"basketball-line",
"battery-2-charge-fill",
"battery-2-charge-line",
"battery-2-fill",
"battery-2-line",
"battery-charge-fill",
"battery-charge-line",
"battery-fill",
"battery-line",
"battery-low-fill",
"battery-low-line",
"battery-saver-fill",
"battery-saver-line",
"battery-share-fill",
"battery-share-line",
"bear-smile-fill",
"bear-smile-line",
"behance-fill",
"behance-line",
"bell-fill",
"bell-line",
"bike-fill",
"bike-line",
"bilibili-fill",
"bilibili-line",
"bill-fill",
"bill-line",
"billiards-fill",
"billiards-line",
"bit-coin-fill",
"bit-coin-line",
"blaze-fill",
"blaze-line",
"bluetooth-connect-fill",
"bluetooth-connect-line",
"bluetooth-fill",
"bluetooth-line",
"blur-off-fill",
"blur-off-line",
"body-scan-fill",
"body-scan-line",
"bold",
"book-2-fill",
"book-2-line",
"book-3-fill",
"book-3-line",
"book-fill",
"book-line",
"book-mark-fill",
"book-mark-line",
"book-open-fill",
"book-open-line",
"book-read-fill",
"book-read-line",
"booklet-fill",
"booklet-line",
"bookmark-2-fill",
"bookmark-2-line",
"bookmark-3-fill",
"bookmark-3-line",
"bookmark-fill",
"bookmark-line",
"boxing-fill",
"boxing-line",
"braces-fill",
"braces-line",
"brackets-fill",
"brackets-line",
"briefcase-2-fill",
"briefcase-2-line",
"briefcase-3-fill",
"briefcase-3-line",
"briefcase-4-fill",
"briefcase-4-line",
"briefcase-5-fill",
"briefcase-5-line",
"briefcase-fill",
"briefcase-line",
"bring-forward",
"bring-to-front",
"broadcast-fill",
"broadcast-line",
"brush-2-fill",
"brush-2-line",
"brush-3-fill",
"brush-3-line",
"brush-4-fill",
"brush-4-line",
"brush-fill",
"brush-line",
"bubble-chart-fill",
"bubble-chart-line",
"bug-2-fill",
"bug-2-line",
"bug-fill",
"bug-line",
"building-2-fill",
"building-2-line",
"building-3-fill",
"building-3-line",
"building-4-fill",
"building-4-line",
"building-fill",
"building-line",
"bus-2-fill",
"bus-2-line",
"bus-fill",
"bus-line",
"bus-wifi-fill",
"bus-wifi-line",
"cactus-fill",
"cactus-line",
"cake-2-fill",
"cake-2-line",
"cake-3-fill",
"cake-3-line",
"cake-fill",
"cake-line",
"calculator-fill",
"calculator-line",
"calendar-2-fill",
"calendar-2-line",
"calendar-check-fill",
"calendar-check-line",
"calendar-event-fill",
"calendar-event-line",
"calendar-fill",
"calendar-line",
"calendar-todo-fill",
"calendar-todo-line",
"camera-2-fill",
"camera-2-line",
"camera-3-fill",
"camera-3-line",
"camera-fill",
"camera-lens-fill",
"camera-lens-line",
"camera-line",
"camera-off-fill",
"camera-off-line",
"camera-switch-fill",
"camera-switch-line",
"capsule-fill",
"capsule-line",
"car-fill",
"car-line",
"car-washing-fill",
"car-washing-line",
"caravan-fill",
"caravan-line",
"cast-fill",
"cast-line",
"cellphone-fill",
"cellphone-line",
"celsius-fill",
"celsius-line",
"centos-fill",
"centos-line",
"character-recognition-fill",
"character-recognition-line",
"charging-pile-2-fill",
"charging-pile-2-line",
"charging-pile-fill",
"charging-pile-line",
"chat-1-fill",
"chat-1-line",
"chat-2-fill",
"chat-2-line",
"chat-3-fill",
"chat-3-line",
"chat-4-fill",
"chat-4-line",
"chat-check-fill",
"chat-check-line",
"chat-delete-fill",
"chat-delete-line",
"chat-download-fill",
"chat-download-line",
"chat-follow-up-fill",
"chat-follow-up-line",
"chat-forward-fill",
"chat-forward-line",
"chat-heart-fill",
"chat-heart-line",
"chat-history-fill",
"chat-history-line",
"chat-new-fill",
"chat-new-line",
"chat-off-fill",
"chat-off-line",
"chat-poll-fill",
"chat-poll-line",
"chat-private-fill",
"chat-private-line",
"chat-quote-fill",
"chat-quote-line",
"chat-settings-fill",
"chat-settings-line",
"chat-smile-2-fill",
"chat-smile-2-line",
"chat-smile-3-fill",
"chat-smile-3-line",
"chat-smile-fill",
"chat-smile-line",
"chat-upload-fill",
"chat-upload-line",
"chat-voice-fill",
"chat-voice-line",
"check-double-fill",
"check-double-line",
"check-fill",
"check-line",
"checkbox-blank-circle-fill",
"checkbox-blank-circle-line",
"checkbox-blank-fill",
"checkbox-blank-line",
"checkbox-circle-fill",
"checkbox-circle-line",
"checkbox-fill",
"checkbox-indeterminate-fill",
"checkbox-indeterminate-line",
"checkbox-line",
"checkbox-multiple-blank-fill",
"checkbox-multiple-blank-line",
"checkbox-multiple-fill",
"checkbox-multiple-line",
"china-railway-fill",
"china-railway-line",
"chrome-fill",
"chrome-line",
"clapperboard-fill",
"clapperboard-line",
"clipboard-fill",
"clipboard-line",
"clockwise-2-fill",
"clockwise-2-line",
"clockwise-fill",
"clockwise-line",
"close-circle-fill",
"close-circle-line",
"close-fill",
"close-line",
"closed-captioning-fill",
"closed-captioning-line",
"cloud-fill",
"cloud-line",
"cloud-off-fill",
"cloud-off-line",
"cloud-windy-fill",
"cloud-windy-line",
"cloudy-2-fill",
"cloudy-2-line",
"cloudy-fill",
"cloudy-line",
"code-box-fill",
"code-box-line",
"code-fill",
"code-line",
"code-s-fill",
"code-s-line",
"code-s-slash-fill",
"code-s-slash-line",
"code-view",
"codepen-fill",
"codepen-line",
"coin-fill",
"coin-line",
"coins-fill",
"coins-line",
"collage-fill",
"collage-line",
"command-fill",
"command-line",
"community-fill",
"community-line",
"compass-2-fill",
"compass-2-line",
"compass-3-fill",
"compass-3-line",
"compass-4-fill",
"compass-4-line",
"compass-discover-fill",
"compass-discover-line",
"compass-fill",
"compass-line",
"compasses-2-fill",
"compasses-2-line",
"compasses-fill",
"compasses-line",
"computer-fill",
"computer-line",
"contacts-book-2-fill",
"contacts-book-2-line",
"contacts-book-fill",
"contacts-book-line",
"contacts-book-upload-fill",
"contacts-book-upload-line",
"contacts-fill",
"contacts-line",
"contrast-2-fill",
"contrast-2-line",
"contrast-drop-2-fill",
"contrast-drop-2-line",
"contrast-drop-fill",
"contrast-drop-line",
"contrast-fill",
"contrast-line",
"copper-coin-fill",
"copper-coin-line",
"copper-diamond-fill",
"copper-diamond-line",
"copyleft-fill",
"copyleft-line",
"copyright-fill",
"copyright-line",
"coreos-fill",
"coreos-line",
"coupon-2-fill",
"coupon-2-line",
"coupon-3-fill",
"coupon-3-line",
"coupon-4-fill",
"coupon-4-line",
"coupon-5-fill",
"coupon-5-line",
"coupon-fill",
"coupon-line",
"cpu-fill",
"cpu-line",
"creative-commons-by-fill",
"creative-commons-by-line",
"creative-commons-fill",
"creative-commons-line",
"creative-commons-nc-fill",
"creative-commons-nc-line",
"creative-commons-nd-fill",
"creative-commons-nd-line",
"creative-commons-sa-fill",
"creative-commons-sa-line",
"creative-commons-zero-fill",
"creative-commons-zero-line",
"criminal-fill",
"criminal-line",
"crop-2-fill",
"crop-2-line",
"crop-fill",
"crop-line",
"css3-fill",
"css3-line",
"cup-fill",
"cup-line",
"currency-fill",
"currency-line",
"cursor-fill",
"cursor-line",
"customer-service-2-fill",
"customer-service-2-line",
"customer-service-fill",
"customer-service-line",
"dashboard-2-fill",
"dashboard-2-line",
"dashboard-3-fill",
"dashboard-3-line",
"dashboard-fill",
"dashboard-line",
"database-2-fill",
"database-2-line",
"database-fill",
"database-line",
"delete-back-2-fill",
"delete-back-2-line",
"delete-back-fill",
"delete-back-line",
"delete-bin-2-fill",
"delete-bin-2-line",
"delete-bin-3-fill",
"delete-bin-3-line",
"delete-bin-4-fill",
"delete-bin-4-line",
"delete-bin-5-fill",
"delete-bin-5-line",
"delete-bin-6-fill",
"delete-bin-6-line",
"delete-bin-7-fill",
"delete-bin-7-line",
"delete-bin-fill",
"delete-bin-line",
"delete-column",
"delete-row",
"device-fill",
"device-line",
"device-recover-fill",
"device-recover-line",
"dingding-fill",
"dingding-line",
"direction-fill",
"direction-line",
"disc-fill",
"disc-line",
"discord-fill",
"discord-line",
"discuss-fill",
"discuss-line",
"dislike-fill",
"dislike-line",
"disqus-fill",
"disqus-line",
"divide-fill",
"divide-line",
"donut-chart-fill",
"donut-chart-line",
"door-closed-fill",
"door-closed-line",
"door-fill",
"door-line",
"door-lock-box-fill",
"door-lock-box-line",
"door-lock-fill",
"door-lock-line",
"door-open-fill",
"door-open-line",
"dossier-fill",
"dossier-line",
"douban-fill",
"douban-line",
"double-quotes-l",
"double-quotes-r",
"download-2-fill",
"download-2-line",
"download-cloud-2-fill",
"download-cloud-2-line",
"download-cloud-fill",
"download-cloud-line",
"download-fill",
"download-line",
"draft-fill",
"draft-line",
"drag-drop-fill",
"drag-drop-line",
"drag-move-2-fill",
"drag-move-2-line",
"drag-move-fill",
"drag-move-line",
"dribbble-fill",
"dribbble-line",
"drive-fill",
"drive-line",
"drizzle-fill",
"drizzle-line",
"drop-fill",
"drop-line",
"dropbox-fill",
"dropbox-line",
"dual-sim-1-fill",
"dual-sim-1-line",
"dual-sim-2-fill",
"dual-sim-2-line",
"dv-fill",
"dv-line",
"dvd-fill",
"dvd-line",
"e-bike-2-fill",
"e-bike-2-line",
"e-bike-fill",
"e-bike-line",
"earth-fill",
"earth-line",
"earthquake-fill",
"earthquake-line",
"edge-fill",
"edge-line",
"edit-2-fill",
"edit-2-line",
"edit-box-fill",
"edit-box-line",
"edit-circle-fill",
"edit-circle-line",
"edit-fill",
"edit-line",
"eject-fill",
"eject-line",
"emotion-2-fill",
"emotion-2-line",
"emotion-fill",
"emotion-happy-fill",
"emotion-happy-line",
"emotion-laugh-fill",
"emotion-laugh-line",
"emotion-line",
"emotion-normal-fill",
"emotion-normal-line",
"emotion-sad-fill",
"emotion-sad-line",
"emotion-unhappy-fill",
"emotion-unhappy-line",
"empathize-fill",
"empathize-line",
"emphasis-cn",
"emphasis",
"english-input",
"equalizer-fill",
"equalizer-line",
"eraser-fill",
"eraser-line",
"error-warning-fill",
"error-warning-line",
"evernote-fill",
"evernote-line",
"exchange-box-fill",
"exchange-box-line",
"exchange-cny-fill",
"exchange-cny-line",
"exchange-dollar-fill",
"exchange-dollar-line",
"exchange-fill",
"exchange-funds-fill",
"exchange-funds-line",
"exchange-line",
"external-link-fill",
"external-link-line",
"eye-2-fill",
"eye-2-line",
"eye-close-fill",
"eye-close-line",
"eye-fill",
"eye-line",
"eye-off-fill",
"eye-off-line",
"facebook-box-fill",
"facebook-box-line",
"facebook-circle-fill",
"facebook-circle-line",
"facebook-fill",
"facebook-line",
"fahrenheit-fill",
"fahrenheit-line",
"feedback-fill",
"feedback-line",
"file-2-fill",
"file-2-line",
"file-3-fill",
"file-3-line",
"file-4-fill",
"file-4-line",
"file-add-fill",
"file-add-line",
"file-chart-2-fill",
"file-chart-2-line",
"file-chart-fill",
"file-chart-line",
"file-cloud-fill",
"file-cloud-line",
"file-code-fill",
"file-code-line",
"file-copy-2-fill",
"file-copy-2-line",
"file-copy-fill",
"file-copy-line",
"file-damage-fill",
"file-damage-line",
"file-download-fill",
"file-download-line",
"file-edit-fill",
"file-edit-line",
"file-excel-2-fill",
"file-excel-2-line",
"file-excel-fill",
"file-excel-line",
"file-fill",
"file-forbid-fill",
"file-forbid-line",
"file-gif-fill",
"file-gif-line",
"file-history-fill",
"file-history-line",
"file-hwp-fill",
"file-hwp-line",
"file-info-fill",
"file-info-line",
"file-line",
"file-list-2-fill",
"file-list-2-line",
"file-list-3-fill",
"file-list-3-line",
"file-list-fill",
"file-list-line",
"file-lock-fill",
"file-lock-line",
"file-mark-fill",
"file-mark-line",
"file-music-fill",
"file-music-line",
"file-paper-2-fill",
"file-paper-2-line",
"file-paper-fill",
"file-paper-line",
"file-pdf-fill",
"file-pdf-line",
"file-ppt-2-fill",
"file-ppt-2-line",
"file-ppt-fill",
"file-ppt-line",
"file-reduce-fill",
"file-reduce-line",
"file-search-fill",
"file-search-line",
"file-settings-fill",
"file-settings-line",
"file-shield-2-fill",
"file-shield-2-line",
"file-shield-fill",
"file-shield-line",
"file-shred-fill",
"file-shred-line",
"file-text-fill",
"file-text-line",
"file-transfer-fill",
"file-transfer-line",
"file-unknow-fill",
"file-unknow-line",
"file-upload-fill",
"file-upload-line",
"file-user-fill",
"file-user-line",
"file-warning-fill",
"file-warning-line",
"file-word-2-fill",
"file-word-2-line",
"file-word-fill",
"file-word-line",
"file-zip-fill",
"file-zip-line",
"film-fill",
"film-line",
"filter-2-fill",
"filter-2-line",
"filter-3-fill",
"filter-3-line",
"filter-fill",
"filter-line",
"filter-off-fill",
"filter-off-line",
"find-replace-fill",
"find-replace-line",
"finder-fill",
"finder-line",
"fingerprint-2-fill",
"fingerprint-2-line",
"fingerprint-fill",
"fingerprint-line",
"fire-fill",
"fire-line",
"firefox-fill",
"firefox-line",
"first-aid-kit-fill",
"first-aid-kit-line",
"flag-2-fill",
"flag-2-line",
"flag-fill",
"flag-line",
"flashlight-fill",
"flashlight-line",
"flask-fill",
"flask-line",
"flight-land-fill",
"flight-land-line",
"flight-takeoff-fill",
"flight-takeoff-line",
"flood-fill",
"flood-line",
"flow-chart",
"flutter-fill",
"flutter-line",
"focus-2-fill",
"focus-2-line",
"focus-3-fill",
"focus-3-line",
"focus-fill",
"focus-line",
"foggy-fill",
"foggy-line",
"folder-2-fill",
"folder-2-line",
"folder-3-fill",
"folder-3-line",
"folder-4-fill",
"folder-4-line",
"folder-5-fill",
"folder-5-line",
"folder-add-fill",
"folder-add-line",
"folder-chart-2-fill",
"folder-chart-2-line",
"folder-chart-fill",
"folder-chart-line",
"folder-download-fill",
"folder-download-line",
"folder-fill",
"folder-forbid-fill",
"folder-forbid-line",
"folder-history-fill",
"folder-history-line",
"folder-info-fill",
"folder-info-line",
"folder-keyhole-fill",
"folder-keyhole-line",
"folder-line",
"folder-lock-fill",
"folder-lock-line",
"folder-music-fill",
"folder-music-line",
"folder-open-fill",
"folder-open-line",
"folder-received-fill",
"folder-received-line",
"folder-reduce-fill",
"folder-reduce-line",
"folder-settings-fill",
"folder-settings-line",
"folder-shared-fill",
"folder-shared-line",
"folder-shield-2-fill",
"folder-shield-2-line",
"folder-shield-fill",
"folder-shield-line",
"folder-transfer-fill",
"folder-transfer-line",
"folder-unknow-fill",
"folder-unknow-line",
"folder-upload-fill",
"folder-upload-line",
"folder-user-fill",
"folder-user-line",
"folder-warning-fill",
"folder-warning-line",
"folder-zip-fill",
"folder-zip-line",
"folders-fill",
"folders-line",
"font-color",
"font-size-2",
"font-size",
"football-fill",
"football-line",
"footprint-fill",
"footprint-line",
"forbid-2-fill",
"forbid-2-line",
"forbid-fill",
"forbid-line",
"format-clear",
"fridge-fill",
"fridge-line",
"fullscreen-exit-fill",
"fullscreen-exit-line",
"fullscreen-fill",
"fullscreen-line",
"function-fill",
"function-line",
"functions",
"funds-box-fill",
"funds-box-line",
"funds-fill",
"funds-line",
"gallery-fill",
"gallery-line",
"gallery-upload-fill",
"gallery-upload-line",
"game-fill",
"game-line",
"gamepad-fill",
"gamepad-line",
"gas-station-fill",
"gas-station-line",
"gatsby-fill",
"gatsby-line",
"genderless-fill",
"genderless-line",
"ghost-2-fill",
"ghost-2-line",
"ghost-fill",
"ghost-line",
"ghost-smile-fill",
"ghost-smile-line",
"gift-2-fill",
"gift-2-line",
"gift-fill",
"gift-line",
"git-branch-fill",
"git-branch-line",
"git-commit-fill",
"git-commit-line",
"git-merge-fill",
"git-merge-line",
"git-pull-request-fill",
"git-pull-request-line",
"git-repository-commits-fill",
"git-repository-commits-line",
"git-repository-fill",
"git-repository-line",
"git-repository-private-fill",
"git-repository-private-line",
"github-fill",
"github-line",
"gitlab-fill",
"gitlab-line",
"global-fill",
"global-line",
"globe-fill",
"globe-line",
"goblet-fill",
"goblet-line",
"google-fill",
"google-line",
"google-play-fill",
"google-play-line",
"government-fill",
"government-line",
"gps-fill",
"gps-line",
"gradienter-fill",
"gradienter-line",
"grid-fill",
"grid-line",
"group-2-fill",
"group-2-line",
"group-fill",
"group-line",
"guide-fill",
"guide-line",
"h-1",
"h-2",
"h-3",
"h-4",
"h-5",
"h-6",
"hail-fill",
"hail-line",
"hammer-fill",
"hammer-line",
"hand-coin-fill",
"hand-coin-line",
"hand-heart-fill",
"hand-heart-line",
"hand-sanitizer-fill",
"hand-sanitizer-line",
"handbag-fill",
"handbag-line",
"hard-drive-2-fill",
"hard-drive-2-line",
"hard-drive-fill",
"hard-drive-line",
"hashtag",
"haze-2-fill",
"haze-2-line",
"haze-fill",
"haze-line",
"hd-fill",
"hd-line",
"heading",
"headphone-fill",
"headphone-line",
"health-book-fill",
"health-book-line",
"heart-2-fill",
"heart-2-line",
"heart-3-fill",
"heart-3-line",
"heart-add-fill",
"heart-add-line",
"heart-fill",
"heart-line",
"heart-pulse-fill",
"heart-pulse-line",
"hearts-fill",
"hearts-line",
"heavy-showers-fill",
"heavy-showers-line",
"history-fill",
"history-line",
"home-2-fill",
"home-2-line",
"home-3-fill",
"home-3-line",
"home-4-fill",
"home-4-line",
"home-5-fill",
"home-5-line",
"home-6-fill",
"home-6-line",
"home-7-fill",
"home-7-line",
"home-8-fill",
"home-8-line",
"home-fill",
"home-gear-fill",
"home-gear-line",
"home-heart-fill",
"home-heart-line",
"home-line",
"home-smile-2-fill",
"home-smile-2-line",
"home-smile-fill",
"home-smile-line",
"home-wifi-fill",
"home-wifi-line",
"honor-of-kings-fill",
"honor-of-kings-line",
"honour-fill",
"honour-line",
"hospital-fill",
"hospital-line",
"hotel-bed-fill",
"hotel-bed-line",
"hotel-fill",
"hotel-line",
"hotspot-fill",
"hotspot-line",
"hq-fill",
"hq-line",
"html5-fill",
"html5-line",
"ie-fill",
"ie-line",
"image-2-fill",
"image-2-line",
"image-add-fill",
"image-add-line",
"image-edit-fill",
"image-edit-line",
"image-fill",
"image-line",
"inbox-archive-fill",
"inbox-archive-line",
"inbox-fill",
"inbox-line",
"inbox-unarchive-fill",
"inbox-unarchive-line",
"increase-decrease-fill",
"increase-decrease-line",
"indent-decrease",
"indent-increase",
"indeterminate-circle-fill",
"indeterminate-circle-line",
"information-fill",
"information-line",
"infrared-thermometer-fill",
"infrared-thermometer-line",
"ink-bottle-fill",
"ink-bottle-line",
"input-cursor-move",
"input-method-fill",
"input-method-line",
"insert-column-left",
"insert-column-right",
"insert-row-bottom",
"insert-row-top",
"instagram-fill",
"instagram-line",
"install-fill",
"install-line",
"invision-fill",
"invision-line",
"italic",
"kakao-talk-fill",
"kakao-talk-line",
"key-2-fill",
"key-2-line",
"key-fill",
"key-line",
"keyboard-box-fill",
"keyboard-box-line",
"keyboard-fill",
"keyboard-line",
"keynote-fill",
"keynote-line",
"knife-blood-fill",
"knife-blood-line",
"knife-fill",
"knife-line",
"landscape-fill",
"landscape-line",
"layout-2-fill",
"layout-2-line",
"layout-3-fill",
"layout-3-line",
"layout-4-fill",
"layout-4-line",
"layout-5-fill",
"layout-5-line",
"layout-6-fill",
"layout-6-line",
"layout-bottom-2-fill",
"layout-bottom-2-line",
"layout-bottom-fill",
"layout-bottom-line",
"layout-column-fill",
"layout-column-line",
"layout-fill",
"layout-grid-fill",
"layout-grid-line",
"layout-left-2-fill",
"layout-left-2-line",
"layout-left-fill",
"layout-left-line",
"layout-line",
"layout-masonry-fill",
"layout-masonry-line",
"layout-right-2-fill",
"layout-right-2-line",
"layout-right-fill",
"layout-right-line",
"layout-row-fill",
"layout-row-line",
"layout-top-2-fill",
"layout-top-2-line",
"layout-top-fill",
"layout-top-line",
"leaf-fill",
"leaf-line",
"lifebuoy-fill",
"lifebuoy-line",
"lightbulb-fill",
"lightbulb-flash-fill",
"lightbulb-flash-line",
"lightbulb-line",
"line-chart-fill",
"line-chart-line",
"line-fill",
"line-height",
"line-line",
"link-m",
"link-unlink-m",
"link-unlink",
"link",
"linkedin-box-fill",
"linkedin-box-line",
"linkedin-fill",
"linkedin-line",
"links-fill",
"links-line",
"list-check-2",
"list-check",
"list-ordered",
"list-settings-fill",
"list-settings-line",
"list-unordered",
"live-fill",
"live-line",
"loader-2-fill",
"loader-2-line",
"loader-3-fill",
"loader-3-line",
"loader-4-fill",
"loader-4-line",
"loader-5-fill",
"loader-5-line",
"loader-fill",
"loader-line",
"lock-2-fill",
"lock-2-line",
"lock-fill",
"lock-line",
"lock-password-fill",
"lock-password-line",
"lock-unlock-fill",
"lock-unlock-line",
"login-box-fill",
"login-box-line",
"login-circle-fill",
"login-circle-line",
"logout-box-fill",
"logout-box-line",
"logout-box-r-fill",
"logout-box-r-line",
"logout-circle-fill",
"logout-circle-line",
"logout-circle-r-fill",
"logout-circle-r-line",
"luggage-cart-fill",
"luggage-cart-line",
"luggage-deposit-fill",
"luggage-deposit-line",
"lungs-fill",
"lungs-line",
"mac-fill",
"mac-line",
"macbook-fill",
"macbook-line",
"magic-fill",
"magic-line",
"mail-add-fill",
"mail-add-line",
"mail-check-fill",
"mail-check-line",
"mail-close-fill",
"mail-close-line",
"mail-download-fill",
"mail-download-line",
"mail-fill",
"mail-forbid-fill",
"mail-forbid-line",
"mail-line",
"mail-lock-fill",
"mail-lock-line",
"mail-open-fill",
"mail-open-line",
"mail-send-fill",
"mail-send-line",
"mail-settings-fill",
"mail-settings-line",
"mail-star-fill",
"mail-star-line",
"mail-unread-fill",
"mail-unread-line",
"mail-volume-fill",
"mail-volume-line",
"map-2-fill",
"map-2-line",
"map-fill",
"map-line",
"map-pin-2-fill",
"map-pin-2-line",
"map-pin-3-fill",
"map-pin-3-line",
"map-pin-4-fill",
"map-pin-4-line",
"map-pin-5-fill",
"map-pin-5-line",
"map-pin-add-fill",
"map-pin-add-line",
"map-pin-fill",
"map-pin-line",
"map-pin-range-fill",
"map-pin-range-line",
"map-pin-time-fill",
"map-pin-time-line",
"map-pin-user-fill",
"map-pin-user-line",
"mark-pen-fill",
"mark-pen-line",
"markdown-fill",
"markdown-line",
"markup-fill",
"markup-line",
"mastercard-fill",
"mastercard-line",
"mastodon-fill",
"mastodon-line",
"medal-2-fill",
"medal-2-line",
"medal-fill",
"medal-line",
"medicine-bottle-fill",
"medicine-bottle-line",
"medium-fill",
"medium-line",
"men-fill",
"men-line",
"mental-health-fill",
"mental-health-line",
"menu-2-fill",
"menu-2-line",
"menu-3-fill",
"menu-3-line",
"menu-4-fill",
"menu-4-line",
"menu-5-fill",
"menu-5-line",
"menu-add-fill",
"menu-add-line",
"menu-fill",
"menu-fold-fill",
"menu-fold-line",
"menu-line",
"menu-unfold-fill",
"menu-unfold-line",
"merge-cells-horizontal",
"merge-cells-vertical",
"message-2-fill",
"message-2-line",
"message-3-fill",
"message-3-line",
"message-fill",
"message-line",
"messenger-fill",
"messenger-line",
"meteor-fill",
"meteor-line",
"mic-2-fill",
"mic-2-line",
"mic-fill",
"mic-line",
"mic-off-fill",
"mic-off-line",
"mickey-fill",
"mickey-line",
"microscope-fill",
"microscope-line",
"microsoft-fill",
"microsoft-line",
"mind-map",
"mini-program-fill",
"mini-program-line",
"mist-fill",
"mist-line",
"money-cny-box-fill",
"money-cny-box-line",
"money-cny-circle-fill",
"money-cny-circle-line",
"money-dollar-box-fill",
"money-dollar-box-line",
"money-dollar-circle-fill",
"money-dollar-circle-line",
"money-euro-box-fill",
"money-euro-box-line",
"money-euro-circle-fill",
"money-euro-circle-line",
"money-pound-box-fill",
"money-pound-box-line",
"money-pound-circle-fill",
"money-pound-circle-line",
"moon-clear-fill",
"moon-clear-line",
"moon-cloudy-fill",
"moon-cloudy-line",
"moon-fill",
"moon-foggy-fill",
"moon-foggy-line",
"moon-line",
"more-2-fill",
"more-2-line",
"more-fill",
"more-line",
"motorbike-fill",
"motorbike-line",
"mouse-fill",
"mouse-line",
"movie-2-fill",
"movie-2-line",
"movie-fill",
"movie-line",
"music-2-fill",
"music-2-line",
"music-fill",
"music-line",
"mv-fill",
"mv-line",
"navigation-fill",
"navigation-line",
"netease-cloud-music-fill",
"netease-cloud-music-line",
"netflix-fill",
"netflix-line",
"newspaper-fill",
"newspaper-line",
"node-tree",
"notification-2-fill",
"notification-2-line",
"notification-3-fill",
"notification-3-line",
"notification-4-fill",
"notification-4-line",
"notification-badge-fill",
"notification-badge-line",
"notification-fill",
"notification-line",
"notification-off-fill",
"notification-off-line",
"npmjs-fill",
"npmjs-line",
"number-0",
"number-1",
"number-2",
"number-3",
"number-4",
"number-5",
"number-6",
"number-7",
"number-8",
"number-9",
"numbers-fill",
"numbers-line",
"nurse-fill",
"nurse-line",
"oil-fill",
"oil-line",
"omega",
"open-arm-fill",
"open-arm-line",
"open-source-fill",
"open-source-line",
"opera-fill",
"opera-line",
"order-play-fill",
"order-play-line",
"organization-chart",
"outlet-2-fill",
"outlet-2-line",
"outlet-fill",
"outlet-line",
"page-separator",
"pages-fill",
"pages-line",
"paint-brush-fill",
"paint-brush-line",
"paint-fill",
"paint-line",
"palette-fill",
"palette-line",
"pantone-fill",
"pantone-line",
"paragraph",
"parent-fill",
"parent-line",
"parentheses-fill",
"parentheses-line",
"parking-box-fill",
"parking-box-line",
"parking-fill",
"parking-line",
"passport-fill",
"passport-line",
"patreon-fill",
"patreon-line",
"pause-circle-fill",
"pause-circle-line",
"pause-fill",
"pause-line",
"pause-mini-fill",
"pause-mini-line",
"paypal-fill",
"paypal-line",
"pen-nib-fill",
"pen-nib-line",
"pencil-fill",
"pencil-line",
"pencil-ruler-2-fill",
"pencil-ruler-2-line",
"pencil-ruler-fill",
"pencil-ruler-line",
"percent-fill",
"percent-line",
"phone-camera-fill",
"phone-camera-line",
"phone-fill",
"phone-find-fill",
"phone-find-line",
"phone-line",
"phone-lock-fill",
"phone-lock-line",
"picture-in-picture-2-fill",
"picture-in-picture-2-line",
"picture-in-picture-exit-fill",
"picture-in-picture-exit-line",
"picture-in-picture-fill",
"picture-in-picture-line",
"pie-chart-2-fill",
"pie-chart-2-line",
"pie-chart-box-fill",
"pie-chart-box-line",
"pie-chart-fill",
"pie-chart-line",
"pin-distance-fill",
"pin-distance-line",
"ping-pong-fill",
"ping-pong-line",
"pinterest-fill",
"pinterest-line",
"pinyin-input",
"pixelfed-fill",
"pixelfed-line",
"plane-fill",
"plane-line",
"plant-fill",
"plant-line",
"play-circle-fill",
"play-circle-line",
"play-fill",
"play-line",
"play-list-2-fill",
"play-list-2-line",
"play-list-add-fill",
"play-list-add-line",
"play-list-fill",
"play-list-line",
"play-mini-fill",
"play-mini-line",
"playstation-fill",
"playstation-line",
"plug-2-fill",
"plug-2-line",
"plug-fill",
"plug-line",
"polaroid-2-fill",
"polaroid-2-line",
"polaroid-fill",
"polaroid-line",
"police-car-fill",
"police-car-line",
"price-tag-2-fill",
"price-tag-2-line",
"price-tag-3-fill",
"price-tag-3-line",
"price-tag-fill",
"price-tag-line",
"printer-cloud-fill",
"printer-cloud-line",
"printer-fill",
"printer-line",
"product-hunt-fill",
"product-hunt-line",
"profile-fill",
"profile-line",
"projector-2-fill",
"projector-2-line",
"projector-fill",
"projector-line",
"psychotherapy-fill",
"psychotherapy-line",
"pulse-fill",
"pulse-line",
"pushpin-2-fill",
"pushpin-2-line",
"pushpin-fill",
"pushpin-line",
"qq-fill",
"qq-line",
"qr-code-fill",
"qr-code-line",
"qr-scan-2-fill",
"qr-scan-2-line",
"qr-scan-fill",
"qr-scan-line",
"question-answer-fill",
"question-answer-line",
"question-fill",
"question-line",
"question-mark",
"questionnaire-fill",
"questionnaire-line",
"quill-pen-fill",
"quill-pen-line",
"radar-fill",
"radar-line",
"radio-2-fill",
"radio-2-line",
"radio-button-fill",
"radio-button-line",
"radio-fill",
"radio-line",
"rainbow-fill",
"rainbow-line",
"rainy-fill",
"rainy-line",
"reactjs-fill",
"reactjs-line",
"record-circle-fill",
"record-circle-line",
"record-mail-fill",
"record-mail-line",
"recycle-fill",
"recycle-line",
"red-packet-fill",
"red-packet-line",
"reddit-fill",
"reddit-line",
"refresh-fill",
"refresh-line",
"refund-2-fill",
"refund-2-line",
"refund-fill",
"refund-line",
"registered-fill",
"registered-line",
"remixicon-fill",
"remixicon-line",
"remote-control-2-fill",
"remote-control-2-line",
"remote-control-fill",
"remote-control-line",
"repeat-2-fill",
"repeat-2-line",
"repeat-fill",
"repeat-line",
"repeat-one-fill",
"repeat-one-line",
"reply-all-fill",
"reply-all-line",
"reply-fill",
"reply-line",
"reserved-fill",
"reserved-line",
"rest-time-fill",
"rest-time-line",
"restart-fill",
"restart-line",
"restaurant-2-fill",
"restaurant-2-line",
"restaurant-fill",
"restaurant-line",
"rewind-fill",
"rewind-line",
"rewind-mini-fill",
"rewind-mini-line",
"rhythm-fill",
"rhythm-line",
"riding-fill",
"riding-line",
"road-map-fill",
"road-map-line",
"roadster-fill",
"roadster-line",
"robot-fill",
"robot-line",
"rocket-2-fill",
"rocket-2-line",
"rocket-fill",
"rocket-line",
"rotate-lock-fill",
"rotate-lock-line",
"rounded-corner",
"route-fill",
"route-line",
"router-fill",
"router-line",
"rss-fill",
"rss-line",
"ruler-2-fill",
"ruler-2-line",
"ruler-fill",
"ruler-line",
"run-fill",
"run-line",
"safari-fill",
"safari-line",
"safe-2-fill",
"safe-2-line",
"safe-fill",
"safe-line",
"sailboat-fill",
"sailboat-line",
"save-2-fill",
"save-2-line",
"save-3-fill",
"save-3-line",
"save-fill",
"save-line",
"scales-2-fill",
"scales-2-line",
"scales-3-fill",
"scales-3-line",
"scales-fill",
"scales-line",
"scan-2-fill",
"scan-2-line",
"scan-fill",
"scan-line",
"scissors-2-fill",
"scissors-2-line",
"scissors-cut-fill",
"scissors-cut-line",
"scissors-fill",
"scissors-line",
"screenshot-2-fill",
"screenshot-2-line",
"screenshot-fill",
"screenshot-line",
"sd-card-fill",
"sd-card-line",
"sd-card-mini-fill",
"sd-card-mini-line",
"search-2-fill",
"search-2-line",
"search-eye-fill",
"search-eye-line",
"search-fill",
"search-line",
"secure-payment-fill",
"secure-payment-line",
"seedling-fill",
"seedling-line",
"send-backward",
"send-plane-2-fill",
"send-plane-2-line",
"send-plane-fill",
"send-plane-line",
"send-to-back",
"sensor-fill",
"sensor-line",
"separator",
"server-fill",
"server-line",
"service-fill",
"service-line",
"settings-2-fill",
"settings-2-line",
"settings-3-fill",
"settings-3-line",
"settings-4-fill",
"settings-4-line",
"settings-5-fill",
"settings-5-line",
"settings-6-fill",
"settings-6-line",
"settings-fill",
"settings-line",
"shape-2-fill",
"shape-2-line",
"shape-fill",
"shape-line",
"share-box-fill",
"share-box-line",
"share-circle-fill",
"share-circle-line",
"share-fill",
"share-forward-2-fill",
"share-forward-2-line",
"share-forward-box-fill",
"share-forward-box-line",
"share-forward-fill",
"share-forward-line",
"share-line",
"shield-check-fill",
"shield-check-line",
"shield-cross-fill",
"shield-cross-line",
"shield-fill",
"shield-flash-fill",
"shield-flash-line",
"shield-keyhole-fill",
"shield-keyhole-line",
"shield-line",
"shield-star-fill",
"shield-star-line",
"shield-user-fill",
"shield-user-line",
"ship-2-fill",
"ship-2-line",
"ship-fill",
"ship-line",
"shirt-fill",
"shirt-line",
"shopping-bag-2-fill",
"shopping-bag-2-line",
"shopping-bag-3-fill",
"shopping-bag-3-line",
"shopping-bag-fill",
"shopping-bag-line",
"shopping-basket-2-fill",
"shopping-basket-2-line",
"shopping-basket-fill",
"shopping-basket-line",
"shopping-cart-2-fill",
"shopping-cart-2-line",
"shopping-cart-fill",
"shopping-cart-line",
"showers-fill",
"showers-line",
"shuffle-fill",
"shuffle-line",
"shut-down-fill",
"shut-down-line",
"side-bar-fill",
"side-bar-line",
"signal-tower-fill",
"signal-tower-line",
"signal-wifi-1-fill",
"signal-wifi-1-line",
"signal-wifi-2-fill",
"signal-wifi-2-line",
"signal-wifi-3-fill",
"signal-wifi-3-line",
"signal-wifi-error-fill",
"signal-wifi-error-line",
"signal-wifi-fill",
"signal-wifi-line",
"signal-wifi-off-fill",
"signal-wifi-off-line",
"sim-card-2-fill",
"sim-card-2-line",
"sim-card-fill",
"sim-card-line",
"single-quotes-l",
"single-quotes-r",
"sip-fill",
"sip-line",
"skip-back-fill",
"skip-back-line",
"skip-back-mini-fill",
"skip-back-mini-line",
"skip-forward-fill",
"skip-forward-line",
"skip-forward-mini-fill",
"skip-forward-mini-line",
"skull-2-fill",
"skull-2-line",
"skull-fill",
"skull-line",
"skype-fill",
"skype-line",
"slack-fill",
"slack-line",
"slice-fill",
"slice-line",
"slideshow-2-fill",
"slideshow-2-line",
"slideshow-3-fill",
"slideshow-3-line",
"slideshow-4-fill",
"slideshow-4-line",
"slideshow-fill",
"slideshow-line",
"smartphone-fill",
"smartphone-line",
"snapchat-fill",
"snapchat-line",
"snowy-fill",
"snowy-line",
"sort-asc",
"sort-desc",
"sound-module-fill",
"sound-module-line",
"soundcloud-fill",
"soundcloud-line",
"space-ship-fill",
"space-ship-line",
"space",
"spam-2-fill",
"spam-2-line",
"spam-3-fill",
"spam-3-line",
"spam-fill",
"spam-line",
"speaker-2-fill",
"speaker-2-line",
"speaker-3-fill",
"speaker-3-line",
"speaker-fill",
"speaker-line",
"spectrum-fill",
"spectrum-line",
"speed-fill",
"speed-line",
"speed-mini-fill",
"speed-mini-line",
"split-cells-horizontal",
"split-cells-vertical",
"spotify-fill",
"spotify-line",
"spy-fill",
"spy-line",
"stack-fill",
"stack-line",
"stack-overflow-fill",
"stack-overflow-line",
"stackshare-fill",
"stackshare-line",
"star-fill",
"star-half-fill",
"star-half-line",
"star-half-s-fill",
"star-half-s-line",
"star-line",
"star-s-fill",
"star-s-line",
"star-smile-fill",
"star-smile-line",
"steam-fill",
"steam-line",
"steering-2-fill",
"steering-2-line",
"steering-fill",
"steering-line",
"stethoscope-fill",
"stethoscope-line",
"sticky-note-2-fill",
"sticky-note-2-line",
"sticky-note-fill",
"sticky-note-line",
"stock-fill",
"stock-line",
"stop-circle-fill",
"stop-circle-line",
"stop-fill",
"stop-line",
"stop-mini-fill",
"stop-mini-line",
"store-2-fill",
"store-2-line",
"store-3-fill",
"store-3-line",
"store-fill",
"store-line",
"strikethrough-2",
"strikethrough",
"subscript-2",
"subscript",
"subtract-fill",
"subtract-line",
"subway-fill",
"subway-line",
"subway-wifi-fill",
"subway-wifi-line",
"suitcase-2-fill",
"suitcase-2-line",
"suitcase-3-fill",
"suitcase-3-line",
"suitcase-fill",
"suitcase-line",
"sun-cloudy-fill",
"sun-cloudy-line",
"sun-fill",
"sun-foggy-fill",
"sun-foggy-line",
"sun-line",
"superscript-2",
"superscript",
"surgical-mask-fill",
"surgical-mask-line",
"surround-sound-fill",
"surround-sound-line",
"survey-fill",
"survey-line",
"swap-box-fill",
"swap-box-line",
"swap-fill",
"swap-line",
"switch-fill",
"switch-line",
"sword-fill",
"sword-line",
"syringe-fill",
"syringe-line",
"t-box-fill",
"t-box-line",
"t-shirt-2-fill",
"t-shirt-2-line",
"t-shirt-air-fill",
"t-shirt-air-line",
"t-shirt-fill",
"t-shirt-line",
"table-2",
"table-alt-fill",
"table-alt-line",
"table-fill",
"table-line",
"tablet-fill",
"tablet-line",
"takeaway-fill",
"takeaway-line",
"taobao-fill",
"taobao-line",
"tape-fill",
"tape-line",
"task-fill",
"task-line",
"taxi-fill",
"taxi-line",
"taxi-wifi-fill",
"taxi-wifi-line",
"team-fill",
"team-line",
"telegram-fill",
"telegram-line",
"temp-cold-fill",
"temp-cold-line",
"temp-hot-fill",
"temp-hot-line",
"terminal-box-fill",
"terminal-box-line",
"terminal-fill",
"terminal-line",
"terminal-window-fill",
"terminal-window-line",
"test-tube-fill",
"test-tube-line",
"text-direction-l",
"text-direction-r",
"text-spacing",
"text-wrap",
"text",
"thermometer-fill",
"thermometer-line",
"thumb-down-fill",
"thumb-down-line",
"thumb-up-fill",
"thumb-up-line",
"thunderstorms-fill",
"thunderstorms-line",
"ticket-2-fill",
"ticket-2-line",
"ticket-fill",
"ticket-line",
"time-fill",
"time-line",
"timer-2-fill",
"timer-2-line",
"timer-fill",
"timer-flash-fill",
"timer-flash-line",
"timer-line",
"todo-fill",
"todo-line",
"toggle-fill",
"toggle-line",
"tools-fill",
"tools-line",
"tornado-fill",
"tornado-line",
"trademark-fill",
"trademark-line",
"traffic-light-fill",
"traffic-light-line",
"train-fill",
"train-line",
"train-wifi-fill",
"train-wifi-line",
"translate-2",
"translate",
"travesti-fill",
"travesti-line",
"treasure-map-fill",
"treasure-map-line",
"trello-fill",
"trello-line",
"trophy-fill",
"trophy-line",
"truck-fill",
"truck-line",
"tumblr-fill",
"tumblr-line",
"tv-2-fill",
"tv-2-line",
"tv-fill",
"tv-line",
"twitch-fill",
"twitch-line",
"twitter-fill",
"twitter-line",
"typhoon-fill",
"typhoon-line",
"u-disk-fill",
"u-disk-line",
"ubuntu-fill",
"ubuntu-line",
"umbrella-fill",
"umbrella-line",
"underline",
"uninstall-fill",
"uninstall-line",
"unsplash-fill",
"unsplash-line",
"upload-2-fill",
"upload-2-line",
"upload-cloud-2-fill",
"upload-cloud-2-line",
"upload-cloud-fill",
"upload-cloud-line",
"upload-fill",
"upload-line",
"usb-fill",
"usb-line",
"user-2-fill",
"user-2-line",
"user-3-fill",
"user-3-line",
"user-4-fill",
"user-4-line",
"user-5-fill",
"user-5-line",
"user-6-fill",
"user-6-line",
"user-add-fill",
"user-add-line",
"user-fill",
"user-follow-fill",
"user-follow-line",
"user-heart-fill",
"user-heart-line",
"user-line",
"user-location-fill",
"user-location-line",
"user-received-2-fill",
"user-received-2-line",
"user-received-fill",
"user-received-line",
"user-search-fill",
"user-search-line",
"user-settings-fill",
"user-settings-line",
"user-shared-2-fill",
"user-shared-2-line",
"user-shared-fill",
"user-shared-line",
"user-smile-fill",
"user-smile-line",
"user-star-fill",
"user-star-line",
"user-unfollow-fill",
"user-unfollow-line",
"user-voice-fill",
"user-voice-line",
"video-add-fill",
"video-add-line",
"video-chat-fill",
"video-chat-line",
"video-download-fill",
"video-download-line",
"video-fill",
"video-line",
"video-upload-fill",
"video-upload-line",
"vidicon-2-fill",
"vidicon-2-line",
"vidicon-fill",
"vidicon-line",
"vimeo-fill",
"vimeo-line",
"vip-crown-2-fill",
"vip-crown-2-line",
"vip-crown-fill",
"vip-crown-line",
"vip-diamond-fill",
"vip-diamond-line",
"vip-fill",
"vip-line",
"virus-fill",
"virus-line",
"visa-fill",
"visa-line",
"voice-recognition-fill",
"voice-recognition-line",
"voiceprint-fill",
"voiceprint-line",
"volume-down-fill",
"volume-down-line",
"volume-mute-fill",
"volume-mute-line",
"volume-off-vibrate-fill",
"volume-off-vibrate-line",
"volume-up-fill",
"volume-up-line",
"volume-vibrate-fill",
"volume-vibrate-line",
"vuejs-fill",
"vuejs-line",
"walk-fill",
"walk-line",
"wallet-2-fill",
"wallet-2-line",
"wallet-3-fill",
"wallet-3-line",
"wallet-fill",
"wallet-line",
"water-flash-fill",
"water-flash-line",
"webcam-fill",
"webcam-line",
"wechat-2-fill",
"wechat-2-line",
"wechat-fill",
"wechat-line",
"wechat-pay-fill",
"wechat-pay-line",
"weibo-fill",
"weibo-line",
"whatsapp-fill",
"whatsapp-line",
"wheelchair-fill",
"wheelchair-line",
"wifi-fill",
"wifi-line",
"wifi-off-fill",
"wifi-off-line",
"window-2-fill",
"window-2-line",
"window-fill",
"window-line",
"windows-fill",
"windows-line",
"windy-fill",
"windy-line",
"wireless-charging-fill",
"wireless-charging-line",
"women-fill",
"women-line",
"wubi-input",
"xbox-fill",
"xbox-line",
"xing-fill",
"xing-line",
"youtube-fill",
"youtube-line",
"zcool-fill",
"zcool-line",
"zhihu-fill",
"zhihu-line",
"zoom-in-fill",
"zoom-in-line",
"zoom-out-fill",
"zoom-out-line",
"zzz-fill",
"zzz-line",
];
module.exports = [
{
url: "/remixIcon/getList",
type: "post",
response(config) {
const { title, pageNo = 1, pageSize = 72 } = config.body;
let mockList = data.filter((item) => {
if (title && item.indexOf(title) < 0) return false;
return true;
});
const pageList = mockList.filter(
(item, index) =>
index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
);
return {
code: 200,
msg: "success",
totalCount: mockList.length,
data: pageList,
};
},
},
];
const totalCount = 2;
const List = [
{
id: "@id",
permission: "admin",
},
{
id: "@id",
permission: "editor",
},
];
module.exports = [
{
url: "/roleManagement/getList",
type: "post",
response(config) {
const { title = "", pageNo = 1, pageSize = 20 } = config.body;
let mockList = List.filter((item) => {
return !(title && item.title.indexOf(title) < 0);
});
const pageList = mockList.filter(
(item, index) =>
index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
);
return {
code: 200,
msg: "success",
totalCount,
data: pageList,
};
},
},
{
url: "/roleManagement/doEdit",
type: "post",
response() {
return {
code: 200,
msg: "模拟保存成功",
};
},
},
{
url: "/roleManagement/doDelete",
type: "post",
response() {
return {
code: 200,
msg: "模拟删除成功",
};
},
},
];
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: "sticky",
name: "Sticky",
component: "views/vab/sticky/index",
meta: { title: "sticky吸附", permissions: ["admin"] },
},
{
path: "log",
name: "Log",
component: "views/vab/errorLog/index",
meta: { title: "错误日志模拟", permissions: ["admin"] },
},
{
path: "more",
name: "More",
component: "views/vab/more/index",
meta: { title: "更多组件", permissions: ["admin"] },
},
],
},
{
path: "/mall",
component: "Layout",
redirect: "noRedirect",
name: "Mall",
meta: {
title: "商城",
icon: "shopping-cart",
permissions: ["admin"],
},
children: [
{
path: "pay",
name: "Pay",
component: "views/mall/pay/index",
meta: {
title: "支付",
noKeepAlive: true,
},
children: null,
},
{
path: "goodsList",
name: "GoodsList",
component: "views/mall/goodsList/index",
meta: {
title: "商品列表",
},
},
{
path: "goodsDetail",
name: "GoodsDetail",
component: "views/mall/goodsDetail/index",
meta: {
title: "商品详情",
},
},
],
},
{
path: "/error",
component: "EmptyLayout",
redirect: "noRedirect",
name: "Error",
meta: { title: "错误页", icon: "bug" },
children: [
{
path: "401",
name: "Error401",
component: "views/401",
meta: { title: "401" },
},
{
path: "404",
name: "Error404",
component: "views/404",
meta: { title: "404" },
},
],
},
];
module.exports = [
{
url: "/menu/navigate",
type: "post",
response() {
return { code: 200, msg: "success", data: data };
},
},
];
const { mock } = require("mockjs");
const { handleRandomImage } = require("../utils");
const List = [];
const count = 999;
for (let i = 0; i < count; i++) {
List.push(
mock({
uuid: "@uuid",
id: "@id",
title: "@csentence(1, 2)",
"status|1": ["published", "draft", "deleted"],
author: "@cname",
datetime: "@datetime",
pageViews: "@integer(300, 5000)",
img: handleRandomImage(200, 200),
smallImg: handleRandomImage(40, 40),
switch: "@boolean",
percent: "@integer(80,99)",
})
);
}
module.exports = [
{
url: "/table/getList",
type: "post",
response(config) {
if (!config.body) {
return {
code: 200,
msg: "success",
totalCount: count,
data: mock({
"data|50": [
{
id: "@id",
title: "@csentence(1, 2)",
"status|1": ["published", "draft", "deleted"],
author: "@cname",
datetime: "@datetime",
pageViews: "@integer(300, 5000)",
img: handleRandomImage(200, 200),
smallImg: handleRandomImage(40, 40),
switch: "@boolean",
percent: "@integer(80,99)",
},
],
}).data,
};
}
const { title = "", pageNo = 1, pageSize = 20 } = config.body;
let mockList = List.filter((item) => {
return !(title && item.title.indexOf(title) < 0);
});
const pageList = mockList.filter(
(item, index) =>
index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
);
return {
code: 200,
msg: "success",
totalCount: count,
data: pageList,
};
},
},
{
url: "/table/doEdit",
type: "post",
response() {
return {
code: 200,
msg: "模拟保存成功",
};
},
},
{
url: "/table/doDelete",
type: "post",
response() {
return {
code: 200,
msg: "模拟删除成功",
};
},
},
];
const data = [
{
id: "1",
parentId: "0",
name: "vue-admin-beautiful科技有限公司",
title: "vue-admin-beautiful科技有限公司",
text: "vue-admin-beautiful科技有限公司",
value: "1",
rank: 1,
children: [
{
id: "32816b88ff72423f960e7d492a386131",
parentId: "1",
name: "1103工作室",
title: "1103工作室",
text: "1103工作室",
value: "32816b88ff72423f960e7d492a386131",
rank: 2,
children: [
{
id: "9e11afc35d55475fb0bd3164b9684cbe",
parentId: "32816b88ff72423f960e7d492a386131",
name: "前端牛逼plus小组",
title: "前端牛逼plus小组",
text: "前端牛逼plus小组",
value: "9e11afc35d55475fb0bd3164b9684cbe",
rank: 3,
children: [
{
id: "4cc1b04635e4444292526c5391699077",
parentId: "9e11afc35d55475fb0bd3164b9684cbe",
name: "组员chuzhixin",
title: "组员chuzhixin",
text: "组员chuzhixin",
value: "4cc1b04635e4444292526c5391699077",
rank: 4,
children: [],
},
],
},
],
},
],
},
];
module.exports = [
{
url: "/tree/list",
type: "post",
response() {
return { code: 200, msg: "success", data };
},
},
];
const data = [];
module.exports = [
{
url: "/upload",
type: "post",
response(config) {
return {
code: 200,
msg: "success",
data: data,
};
},
},
];
const accessTokens = {
admin: "admin-accessToken",
editor: "editor-accessToken",
test: "test-accessToken",
};
module.exports = [
{
url: "/publicKey",
type: "post",
response() {
return {
code: 200,
msg: "success",
data: {
mockServer: true,
publicKey:
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBT2vr+dhZElF73FJ6xiP181txKWUSNLPQQlid6DUJhGAOZblluafIdLmnUyKE8mMHhT3R+Ib3ssZcJku6Hn72yHYj/qPkCGFv0eFo7G+GJfDIUeDyalBN0QsuiE/XzPHJBuJDfRArOiWvH0BXOv5kpeXSXM8yTt5Na1jAYSiQ/wIDAQAB",
},
};
},
},
{
url: "/login",
type: "post",
response(config) {
const { username } = config.body;
const accessToken = accessTokens[username];
if (!accessToken) {
return {
code: 500,
msg: "帐户或密码不正确。",
};
}
return {
code: 200,
msg: "success",
data: { accessToken },
};
},
},
{
url: "/register",
type: "post",
response() {
return {
code: 200,
msg: "模拟注册成功",
};
},
},
{
url: "/userInfo",
type: "post",
response(config) {
const { accessToken } = config.body;
let permissions = ["admin"];
let username = "admin";
if ("admin-accessToken" === accessToken) {
permissions = ["admin"];
username = "admin";
}
if ("editor-accessToken" === accessToken) {
permissions = ["editor"];
username = "editor";
}
if ("test-accessToken" === accessToken) {
permissions = ["admin", "editor"];
username = "test";
}
return {
code: 200,
msg: "success",
data: {
permissions,
username,
"avatar|1": [
"https://i.gtimg.cn/club/item/face/img/2/15922_100.gif",
"https://i.gtimg.cn/club/item/face/img/8/15918_100.gif",
],
},
};
},
},
{
url: "/logout",
type: "post",
response() {
return {
code: 200,
msg: "success",
};
},
},
];
const totalCount = 3;
const List = [
{
id: "@id",
username: "admin",
password: "admin",
email: "@email",
permissions: ["admin"],
datatime: "@datetime",
},
{
id: "@id",
username: "editor",
password: "editor",
email: "@email",
permissions: ["editor"],
datatime: "@datetime",
},
{
id: "@id",
username: "test",
password: "test",
email: "@email",
permissions: ["admin", "editor"],
datatime: "@datetime",
},
];
module.exports = [
{
url: "/userManagement/getList",
type: "post",
response(config) {
const { title = "", pageNo = 1, pageSize = 20 } = config.body;
let mockList = List.filter((item) => {
if (title && item.title.indexOf(title) < 0) return false;
return true;
});
const pageList = mockList.filter(
(item, index) =>
index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
);
return {
code: 200,
msg: "success",
totalCount,
data: pageList,
};
},
},
{
url: "/userManagement/doEdit",
type: "post",
response() {
return {
code: 200,
msg: "模拟保存成功",
};
},
},
{
url: "/userManagement/doDelete",
type: "post",
response() {
return {
code: 200,
msg: "模拟删除成功",
};
},
},
];
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 导入所有 controller 模块,npm run serve时在node环境中自动输出controller文件夹下Mock接口,请勿修改。
*/
const { handleMockArray } = require("./utils");
const mocks = [];
const mockArray = handleMockArray();
mockArray.forEach((item) => {
const obj = require(item);
mocks.push(...obj);
});
module.exports = {
mocks,
};
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}}
*/
const registerRoutes = (app) => {
let mockLastIndex;
const { mocks } = require("./index.js");
const mocksForServer = mocks.map((route) => {
return responseFake(route.url, route.type, route.response);
});
for (const mock of mocksForServer) {
app[mock.type](mock.url, mock.response);
mockLastIndex = app._router.stack.length;
}
const mockRoutesLength = Object.keys(mocksForServer).length;
return {
mockRoutesLength: mockRoutesLength,
mockStartIndex: mockLastIndex - mockRoutesLength,
};
};
/**
*
* @param url
* @param type
* @param respond
* @returns {{response(*=, *=): void, type: (*|string), url: RegExp}}
*/
const responseFake = (url, type, respond) => {
return {
url: new RegExp(`${baseURL}${url}`),
type: type || "get",
response(req, res) {
res.status(200);
if (JSON.stringify(req.body) !== "{}") {
console.log(chalk.green(`> 请求地址:${req.path}`));
console.log(chalk.green(`> 请求参数:${JSON.stringify(req.body)}\n`));
} else {
console.log(chalk.green(`> 请求地址:${req.path}\n`));
}
res.json(
Mock.mock(respond instanceof Function ? respond(req, res) : respond)
);
},
};
};
/**
*
* @param app
*/
module.exports = (app) => {
app.use(bodyParser.json());
app.use(
bodyParser.urlencoded({
extended: true,
})
);
const mockRoutes = registerRoutes(app);
let mockRoutesLength = mockRoutes.mockRoutesLength;
let mockStartIndex = mockRoutes.mockStartIndex;
chokidar
.watch(mockDir, {
ignored: /mock-server/,
ignoreInitial: true,
})
.on("all", (event) => {
if (event === "change" || event === "add") {
try {
app._router.stack.splice(mockStartIndex, mockRoutesLength);
Object.keys(require.cache).forEach((item) => {
if (item.includes(mockDir)) {
delete require.cache[require.resolve(item)];
}
});
const mockRoutes = registerRoutes(app);
mockRoutesLength = mockRoutes.mockRoutesLength;
mockStartIndex = mockRoutes.mockStartIndex;
} catch (error) {
console.log(chalk.red(error));
}
}
});
};
const { Random } = require("mockjs");
const { join } = require("path");
const fs = require("fs");
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 随机生成图片url。
* @param width
* @param height
* @returns {string}
*/
function handleRandomImage(width = 50, height = 50) {
return `https://picsum.photos/${width}/${height}?random=${Random.guid()}`;
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 处理所有 controller 模块,npm run serve时在node环境中自动输出controller文件夹下Mock接口,请勿修改。
* @returns {[]}
*/
function handleMockArray() {
const mockArray = [];
const getFiles = (jsonPath) => {
const jsonFiles = [];
const findJsonFile = (path) => {
const files = fs.readdirSync(path);
files.forEach((item) => {
const fPath = join(path, item);
const stat = fs.statSync(fPath);
if (stat.isDirectory() === true) findJsonFile(item);
if (stat.isFile() === true) jsonFiles.push(item);
});
};
findJsonFile(jsonPath);
jsonFiles.forEach((item) => mockArray.push(`./controller/${item}`));
};
getFiles("mock/controller");
return mockArray;
}
module.exports = {
handleRandomImage,
handleMockArray,
};
{
"name": "vue-admin-beautiful",
"version": "1.0.0",
"author": "chuzhixin 1204505056@qq.com",
"participants": [],
"homepage": "https://chu1204505056.gitee.io/vue-admin-beautiful",
"publishConfig": {
"registry": "https://npm.pkg.github.com/"
},
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"build:report": "vue-cli-service build --report",
"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-config-prettier-check",
"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"
},
"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.20.0",
"better-scroll": "^2.0.4",
"clipboard": "^2.0.6",
"codemirror": "^5.58.1",
"core-js": "^3.6.5",
"dayjs": "^1.9.0",
"echarts": "^4.9.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.20",
"maptalks": "^0.49.1",
"mapv": "^2.0.57",
"nprogress": "^0.2.0",
"qs": "^6.9.4",
"screenfull": "^5.0.2",
"vue": "^2.6.12",
"vue-amap": "^0.5.10",
"vue-echarts": "^5.0.0-beta.0",
"vue-qart": "^2.2.0",
"vue-router": "^3.4.5",
"vuedraggable": "^2.24.1",
"vuex": "^3.5.1",
"zx-comparison": "^1.0.3",
"zx-count": "^0.3.7",
"zx-icon": "^1.1.9",
"zx-keel": "^0.9.4",
"zx-layouts": "^0.6.13",
"zx-magnifie": "^0.4.0",
"zx-markdown-editor": "^0.0.2",
"zx-player": "^1.0.1",
"zx-quill": "^0.0.2",
"zx-templates": "^0.0.22",
"zx-verify": "^0.0.2"
},
"devDependencies": {
"@babel/register": "^7.11.5",
"@vue/cli-plugin-babel": "^4.5.6",
"@vue/cli-plugin-eslint": "^4.5.6",
"@vue/cli-plugin-router": "^4.5.6",
"@vue/cli-plugin-vuex": "^4.5.6",
"@vue/cli-service": "^4.5.6",
"@vue/eslint-config-prettier": "^6.0.0",
"autoprefixer": "^10.0.1",
"babel-eslint": "^10.1.0",
"babel-plugin-dynamic-import-node": "^2.3.3",
"compression-webpack-plugin": "^6.0.2",
"eslint": "^7.10.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-vue": "^6.2.2",
"filemanager-webpack-plugin": "^2.0.5",
"husky": "^4.3.0",
"image-webpack-loader": "^7.0.1",
"increase-memory-limit": "^1.0.7",
"lint-staged": "^10.4.0",
"mockjs": "^1.1.0",
"plop": "^2.7.4",
"prettier": "^2.1.2",
"sass": "^1.26.11",
"sass-loader": "^10.0.2",
"script-loader": "^0.7.2",
"stylelint": "^13.7.2",
"stylelint-config-prettier": "^8.0.2",
"stylelint-config-recess-order": "^2.1.0",
"svg-sprite-loader": "^5.0.0",
"svgo": "^1.3.2",
"vue-template-compiler": "^2.6.12",
"webpackbar": "^4.0.0"
},
"keywords": [
"vue",
"admin",
"dashboard",
"element-ui",
"vue-admin",
"element-admin",
"boilerplate",
"admin-template",
"management-system"
],
"engines": {
"node": ">=8.9",
"npm": ">= 3.0.0"
}
}
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);
};
module.exports = {
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: true,
singleQuote: false,
quoteProps: "as-needed",
jsxSingleQuote: false,
trailingComma: "es5",
bracketSpacing: true,
jsxBracketSameLine: false,
arrowParens: "always",
htmlWhitespaceSensitivity: "ignore",
vueIndentScriptAndStyle: true,
endOfLine: "lf",
};
<!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>
.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;
}
}
#!/usr/bin/env bash
set -e
git init
git add -A
git commit -m '🎉🎉🎉仓库重置到2020年9月29日,Vue2.6最后一个版本,之前版本不再支持,具体请查阅文档,Vue 3.0版本即将发布请耐心等待!!!'
git push -f "https://${access_token}@github.com/chuzhixin/vue-admin-beautiful.git" master
exec /bin/bash
<template>
<div id="vue-admin-beautiful">
<router-view />
</div>
</template>
<script>
export default {
name: "App",
mounted() {},
};
</script>
import request from "@/utils/request";
export function getList(data) {
return request({
url: "/ad/getList",
method: "get",
data,
});
}
import request from "@/utils/request";
export function getList(data) {
return request({
url: "/blacklist/getList",
method: "post",
data,
});
}
import request from "@/utils/request";
export function getList(data) {
return request({
url: "/changeLog/getList",
method: "post",
data,
});
}
import request from "@/utils/request";
export function getIconList(data) {
return request({
url: "/colorfulIcon/getList",
method: "post",
data,
});
}
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,
});
}
import request from "@/utils/request";
export function getList(data) {
return request({
url: "/goodsDetail/getList",
method: "post",
data,
});
}
import request from "@/utils/request";
export function getList(data) {
return request({
url: "/goodsList/getList",
method: "post",
data,
});
}
import request from "@/utils/request";
export function getIconList(data) {
return request({
url: "/icon/getList",
method: "post",
data,
});
}
import request from "axios";
export function getList() {
return request({
url: "https://cdn.jsdelivr.net/gh/prettier/prettier@master/docs/options.md",
method: "get",
});
}
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,
});
}
import request from "@/utils/request";
export function getNoticeList() {
return request({
url: "/notice/getList",
method: "post",
});
}
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,
});
}
import request from "@/utils/request";
export function getPublicKey() {
return request({
url: "/publicKey",
method: "post",
});
}
import request from "@/utils/request";
export function getIconList(data) {
return request({
url: "/remixIcon/getList",
method: "post",
data,
});
}
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,
});
}
import request from "@/utils/request";
export function getRouterList(data) {
return request({
url: "/menu/navigate",
method: "post",
data,
});
}
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,
});
}
import request from "@/utils/request";
export function getTreeList(data) {
return request({
url: "/tree/list",
method: "post",
data,
});
}
import request from "@/utils/request";
import { encryptedData } from "@/utils/encrypt";
import { loginRSA, tokenName } from "@/config/settings";
export async function login(data) {
if (loginRSA) {
data = await encryptedData(data);
}
return request({
url: "/login",
method: "post",
data,
});
}
export function getUserInfo(accessToken) {
return request({
url: "/userInfo",
method: "post",
data: {
[tokenName]: accessToken,
},
});
}
export function logout() {
return request({
url: "/logout",
method: "post",
});
}
export function register() {
return request({
url: "/register",
method: "post",
});
}
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,
});
}
import Vue from "vue";
import { ColorfullIcon } from "@/layouts/components";
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);
<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>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1"
xmlns="http://www.w3.org/2000/svg"
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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
/**
* @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,
progressBar,
recordRoute,
routesWhiteList,
} 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时,创建虚拟权限
await store.dispatch("user/setPermissions", ["admin"]);
permissions = ["admin"];
} else {
permissions = await store.dispatch("user/getUserInfo");
}
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();
});
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 全局变量配置
*/
module.exports = {
// 开发以及部署时的URL
publicPath: "",
// 生产环境构建文件的目录名
outputDir: "dist",
// 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。
assetsDir: "static",
// 开发环境每次保存时是否输出为eslint编译警告
lintOnSave: true,
// 进行编译的依赖
transpileDependencies: ["vue-echarts", "resize-detector", "zx-layouts"],
// 默认的接口地址 如果是开发环境和生产环境走vab-mock-server,当然你也可以选择自己配置成需要的接口地址
baseURL:
process.env.NODE_ENV === "development"
? "vab-mock-server"
: "vab-mock-server",
//标题 (包括初次加载雪花屏的标题 页面的标题 浏览器的标题)
title: "vue-admin-beautiful",
//简写
abbreviation: "vab",
//开发环境端口号
devPort: "80",
//版本号
version: process.env.VUE_APP_VERSION,
//烦请保留package.json作者信息 保留版权可免费商用 如需去除并自定义为自己企业的版权请联系群主QQ 1204505056 需支付299元 恶意修改发生纠纷及出现任何问题 由修改人自行承担
copyright: process.env.VUE_APP_AUTHOR,
//是否显示页面底部版权信息,建议您显示,当然您也可以选择不显示,不管您是付费用户还是未付费用户您都有选择显示或者不显示的权利
footerCopyright: process.env.NODE_ENV !== "development",
//是否显示右上角github图标
githubCorner: process.env.NODE_ENV !== "development",
//是否显示顶部进度条
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,支持String、Array、int多种类型
successCode: [200, 0],
//登录失效code
invalidCode: 402,
//无权限code
noPermissionCode: 401,
//是否显示在页面高亮错误
errorLog: ["development", "test", "production"],
//是否开启登录拦截
loginInterception: true,
//是否开启登录RSA加密
loginRSA: true,
//是否依据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",
//是否显示终端donation打印
donation: true,
};
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 导入所有 controller 模块,浏览器环境中自动输出controller文件夹下Mock接口,请勿修改。
*/
import Mock from "mockjs";
import { paramObj } from "@/utils";
const mocks = [];
const files = require.context("../../mock/controller", false, /\.js$/);
files.keys().forEach((key) => {
const obj = files(key);
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)
);
}
}
<template>
<router-view />
</template>
<template>
<div class="vab-ad">
<el-carousel
v-if="adList"
height="30px"
direction="vertical"
:autoplay="true"
:interval="3000"
indicator-position="none"
>
<el-carousel-item v-for="(item, index) in adList" :key="index">
<el-tag type="warning">Ad</el-tag>
<a target="_blank" :href="item.url">{{ item.title }}</a>
</el-carousel-item>
</el-carousel>
</div>
</template>
<script>
import { getList } from "@/api/ad";
export default {
data() {
return {
nodeEnv: process.env.NODE_ENV,
adList: [],
};
},
created() {
this.fetchData();
},
methods: {
async fetchData() {
const { data } = await getList();
this.adList = data;
},
},
};
</script>
<style lang="scss" scoped>
.vab-ad {
height: 30px;
padding-right: $base-padding;
padding-left: $base-padding;
line-height: 30px;
cursor: pointer;
background: #eef1f6;
box-shadow: 0 -1px 2px rgba(0, 21, 41, 0.08) inset;
a {
color: #999;
}
}
</style>
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 公共布局导出,已封装成npm,便于此后在线升级,当然也存在一定的弊端,给开发者自定义增加了一定的困难,如果您一定要进行高度自定义,请仔细阅读VIP群文档,layouts本地化篇
*/
export { default as ColorfullIcon } from "zx-layouts/ColorfullIcon";
export { default as RemixIcon } from "zx-layouts/RemixIcon";
export { default as VabDrag } from "zx-layouts/Drag";
export { default as VabPermissions } from "zx-layouts/Permissions";
export { default as VabQueryForm } from "zx-layouts/VabQueryForm/export";
export { default as Logo } from "zx-layouts/Logo";
export { default as Avatar } from "zx-layouts/Avatar";
export { default as Ad } from "./Ad";
export { default as AppMain } from "zx-layouts/AppMain";
export { default as TagsBar } from "zx-layouts/TagsBar";
export { default as SideBar } from "zx-layouts/SideBar";
export { default as Breadcrumb } from "zx-layouts/Breadcrumb";
export { default as FullScreenBar } from "zx-layouts/FullScreenBar";
export { default as ErrorLog } from "zx-layouts/ErrorLog";
export { default as ThemeBar } from "zx-layouts/ThemeBar";
export { default as TopBar } from "zx-layouts/TopBar";
export { default as NavBar } from "zx-layouts/NavBar";
<template>
<div class="vue-admin-beautiful-wrapper" :class="classObj">
<div
v-if="'horizontal' === layout"
class="layout-container-horizontal"
:class="{
fixed: header === 'fixed',
'no-tags-bar': tagsBar === 'false' || tagsBar === false,
}"
>
<div :class="header === 'fixed' ? 'fixed-header' : ''">
<top-bar></top-bar>
<div
v-if="tagsBar === 'true' || tagsBar === true"
:class="{ 'tag-view-show': tagsBar }"
>
<div class="vab-main">
<tags-bar></tags-bar>
</div>
</div>
</div>
<div class="vab-main main-padding">
<ad></ad>
<app-main></app-main>
</div>
</div>
<div
v-else
class="layout-container-vertical"
:class="{
fixed: header === 'fixed',
'no-tags-bar': tagsBar === 'false' || tagsBar === false,
}"
>
<div
v-if="device === 'mobile' && collapse === false"
class="mask"
@click="handleFoldSideBar"
/>
<side-bar></side-bar>
<div class="vab-main" :class="collapse ? 'is-collapse-main' : ''">
<div :class="header === 'fixed' ? 'fixed-header' : ''">
<nav-bar></nav-bar>
<tags-bar v-if="tagsBar === 'true' || tagsBar === true" />
</div>
<ad></ad>
<app-main></app-main>
</div>
</div>
<el-backtop></el-backtop>
</div>
</template>
<script>
import { Ad, AppMain, NavBar, SideBar, TagsBar, TopBar } from "./components";
import { mapActions, mapGetters } from "vuex";
import { tokenName } from "@/config/settings";
export default {
name: "Layout",
components: {
Ad,
TopBar,
NavBar,
SideBar,
AppMain,
TagsBar,
},
data() {
return { oldLayout: "" };
},
computed: {
...mapGetters({
layout: "settings/layout",
tagsBar: "settings/tagsBar",
collapse: "settings/collapse",
header: "settings/header",
device: "settings/device",
}),
classObj() {
return {
mobile: this.device === "mobile",
};
},
},
beforeMount() {
window.addEventListener("resize", this.handleResize);
},
beforeDestroy() {
window.removeEventListener("resize", this.handleResize);
},
mounted() {
this.oldLayout = this.layout;
const userAgent = navigator.userAgent;
if (userAgent.includes("Juejin")) {
this.$baseAlert(
"vue-admin-beautiful不支持在掘金内置浏览器演示,请手动复制以下地址到浏览器中查看http://mpfhrd48.sanxing.uz7.cn/vue-admin-beautiful"
);
}
const isMobile = this.handleIsMobile();
if (isMobile) {
if (isMobile) {
//横向布局时如果是手机端访问那么改成纵向版
this.$store.dispatch("settings/changeLayout", "vertical");
} else {
this.$store.dispatch("settings/changeLayout", this.oldLayout);
}
this.$store.dispatch("settings/toggleDevice", "mobile");
setTimeout(() => {
this.$store.dispatch("settings/foldSideBar");
}, 2000);
} else {
this.$store.dispatch("settings/openSideBar");
}
this.$nextTick(() => {
window.addEventListener(
"storage",
(e) => {
if (e.key === tokenName || e.key === null) window.location.reload();
if (e.key === tokenName && e.value === null)
window.location.reload();
},
false
);
});
},
methods: {
...mapActions({
handleFoldSideBar: "settings/foldSideBar",
}),
handleIsMobile() {
return document.body.getBoundingClientRect().width - 1 < 992;
},
handleResize() {
if (!document.hidden) {
const isMobile = this.handleIsMobile();
if (isMobile) {
//横向布局时如果是手机端访问那么改成纵向版
this.$store.dispatch("settings/changeLayout", "vertical");
} else {
this.$store.dispatch("settings/changeLayout", this.oldLayout);
}
this.$store.dispatch(
"settings/toggleDevice",
isMobile ? "mobile" : "desktop"
);
}
},
},
};
</script>
<style lang="scss" scoped>
@mixin fix-header {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: $base-z-index - 2;
width: 100%;
overflow: hidden;
}
.vue-admin-beautiful-wrapper {
position: relative;
width: 100%;
height: 100%;
.layout-container-horizontal {
position: relative;
&.fixed {
padding-top: calc(#{$base-top-bar-height} + #{$base-tags-bar-height});
}
&.fixed.no-tags-bar {
padding-top: $base-top-bar-height;
}
::v-deep {
.vab-main {
width: 88%;
margin: auto;
}
.fixed-header {
@include fix-header;
}
.tag-view-show {
background: $base-color-white;
box-shadow: $base-box-shadow;
}
.nav-bar-container {
.fold-unfold {
display: none;
}
}
.main-padding {
.app-main-container {
margin-top: $base-padding;
margin-bottom: $base-padding;
background: $base-color-white;
}
}
}
}
.layout-container-vertical {
position: relative;
.mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: $base-z-index - 1;
width: 100%;
height: 100vh;
overflow: hidden;
background: #000;
opacity: 0.5;
}
&.fixed {
padding-top: calc(#{$base-nav-bar-height} + #{$base-tags-bar-height});
}
&.fixed.no-tags-bar {
padding-top: $base-nav-bar-height;
}
.vab-main {
position: relative;
min-height: 100%;
margin-left: $base-left-menu-width;
background: #f6f8f9;
transition: $base-transition;
::v-deep {
.fixed-header {
@include fix-header;
left: $base-left-menu-width;
width: $base-right-content-width;
box-shadow: $base-box-shadow;
transition: $base-transition;
}
.nav-bar-container {
position: relative;
box-sizing: border-box;
}
.tags-bar-container {
box-sizing: border-box;
}
.app-main-container {
width: calc(100% - #{$base-padding} - #{$base-padding});
margin: $base-padding auto;
background: $base-color-white;
border-radius: $base-border-radius;
}
}
&.is-collapse-main {
margin-left: $base-left-menu-width-min;
::v-deep {
.fixed-header {
left: $base-left-menu-width-min;
width: calc(100% - 65px);
}
}
}
}
}
/* 手机端开始 */
&.mobile {
::v-deep {
.el-pager,
.el-pagination__jump {
display: none;
}
.layout-container-vertical {
.el-scrollbar.side-bar-container.is-collapse {
width: 0;
}
.vab-main {
width: 100%;
margin-left: 0;
}
}
.vab-main {
.fixed-header {
left: 0 !important;
width: 100% !important;
}
}
}
}
/* 手机端结束 */
}
</style>
import Vue from "vue";
import App from "./App";
import store from "./store";
import router from "./router";
import "./plugins";
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 生产环境默认都使用mock,如果正式用于生产环境时,记得去掉
*/
if (process.env.NODE_ENV === "production") {
const { mockXHR } = require("@/config/static");
mockXHR();
}
Vue.config.productionTip = false;
new Vue({
el: "#vue-admin-beautiful",
router,
store,
render: (h) => h(App),
});
import "echarts";
import "echarts/map/js/china";
import "echarts/map/js/world";
import "echarts-wordcloud";
import VabChart from "vue-echarts";
import theme from "./vab-echarts-theme.json";
VabChart.registerTheme("vab-echarts-theme", theme);
export default VabChart;
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",
});
/* 公共引入,勿随意修改,修改时需经过确认 */
import Vue from "vue";
import "./element";
import "./support";
import "@/styles/vab.scss";
import "@/remixIcon";
import "@/colorfulIcon";
import "@/config/permission";
import "@/utils/errorLog";
import "./vabIcon";
import Vab from "@/utils/vab";
import { VabDrag, VabPermissions, VabQueryForm } from "@/layouts/components";
import VabCount from "zx-count";
Vue.use(Vab);
Vue.use(VabPermissions);
Vue.use(VabDrag);
Vue.use(VabQueryForm);
Vue.use(VabCount);
import { MessageBox } from "element-ui";
import { donation } from "@/config/settings";
import { dependencies, repository } from "../../package.json";
if (!!window.ActiveXObject || "ActiveXObject" in window) {
MessageBox({
title: "温馨提示",
message:
'自2015年3月起,微软已宣布弃用IE,且不再对IE提供任何更新维护,请<a target="_blank" style="color:blue" href="https://www.microsoft.com/zh-cn/edge/">点击此处</a>访问微软官网更新浏览器,如果您使用的是双核浏览器,请您切换浏览器内核为极速模式',
type: "warning",
showClose: false,
showConfirmButton: false,
closeOnClickModal: false,
closeOnPressEscape: false,
closeOnHashChange: false,
dangerouslyUseHTMLString: true,
});
}
if (!dependencies["zx-icon"] || !dependencies["zx-layouts"]) {
document.body.innerHTML = "";
}
{
"color": ["#1890FF", "#36CBCB", "#4ECB73", "#FBD437", "#F2637B", "#975FE5"],
"backgroundColor": "rgba(252,252,252,0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#666666"
},
"subtextStyle": {
"color": "#999999"
}
},
"line": {
"itemStyle": {
"normal": {
"borderWidth": "2"
}
},
"lineStyle": {
"normal": {
"width": "3"
}
},
"symbolSize": "8",
"symbol": "emptyCircle",
"smooth": false
},
"radar": {
"itemStyle": {
"normal": {
"borderWidth": "2"
}
},
"lineStyle": {
"normal": {
"width": "3"
}
},
"symbolSize": "8",
"symbol": "emptyCircle",
"smooth": false
},
"bar": {
"itemStyle": {
"normal": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
},
"emphasis": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
}
}
},
"pie": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"scatter": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"boxplot": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"parallel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"sankey": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"funnel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"gauge": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"candlestick": {
"itemStyle": {
"normal": {
"color": "#e6a0d2",
"color0": "transparent",
"borderColor": "#e6a0d2",
"borderColor0": "#1890FF",
"borderWidth": "2"
}
}
},
"graph": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"lineStyle": {
"normal": {
"width": "1",
"color": "#cccccc"
}
},
"symbolSize": "8",
"symbol": "emptyCircle",
"smooth": false,
"color": ["#1890FF", "#36CBCB", "#4ECB73", "#FBD437", "#F2637B", "#975FE5"],
"label": {
"normal": {
"textStyle": {
"color": "#ffffff"
}
}
}
},
"map": {
"itemStyle": {
"normal": {
"areaColor": "#eeeeee",
"borderColor": "#aaaaaa",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(63,177,227,0.25)",
"borderColor": "#1890FF",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#ffffff"
}
},
"emphasis": {
"textStyle": {
"color": "#1890FF"
}
}
}
},
"geo": {
"itemStyle": {
"normal": {
"areaColor": "#eeeeee",
"borderColor": "#aaaaaa",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(63,177,227,0.25)",
"borderColor": "#1890FF",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#ffffff"
}
},
"emphasis": {
"textStyle": {
"color": "#1890FF"
}
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#eeeeee"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"valueAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#eeeeee"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"logAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#eeeeee"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#eeeeee"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"toolbox": {
"iconStyle": {
"normal": {
"borderColor": "#999999"
},
"emphasis": {
"borderColor": "#666666"
}
}
},
"legend": {
"textStyle": {
"color": "#999999"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "#ffffff",
"width": 1
},
"crossStyle": {
"color": "#ffffff",
"width": 1
}
}
},
"timeline": {
"lineStyle": {
"color": "#4ECB73",
"width": 1
},
"itemStyle": {
"normal": {
"color": "#4ECB73",
"borderWidth": 1
},
"emphasis": {
"color": "#4ECB73"
}
},
"controlStyle": {
"normal": {
"color": "#4ECB73",
"borderColor": "#4ECB73",
"borderWidth": 0.5
},
"emphasis": {
"color": "#4ECB73",
"borderColor": "#4ECB73",
"borderWidth": 0.5
}
},
"checkpointStyle": {
"color": "#1890FF",
"borderColor": "rgba(63,177,227,0.15)"
},
"label": {
"normal": {
"textStyle": {
"color": "#4ECB73"
}
},
"emphasis": {
"textStyle": {
"color": "#4ECB73"
}
}
}
},
"visualMap": {
"color": ["#1890FF", "#afe8ff"]
},
"dataZoom": {
"backgroundColor": "rgba(255,255,255,0)",
"dataBackgroundColor": "rgba(222,222,222,1)",
"fillerColor": "rgba(114,230,212,0.25)",
"handleColor": "#cccccc",
"handleSize": "100%",
"textStyle": {
"color": "#999999"
}
},
"markPoint": {
"label": {
"normal": {
"textStyle": {
"color": "#ffffff"
}
},
"emphasis": {
"textStyle": {
"color": "#ffffff"
}
}
}
}
}
import VabComparison from "zx-comparison";
export default VabComparison;
import Vue from "vue";
import VabIcon from "zx-icon";
Vue.component("vab-icon", VabIcon);
import { Heading, Img, Keel, Text } from "zx-keel";
import "zx-keel/dist/zx-keel.css";
const VabKeel = Keel;
const VabKeelHeading = Heading;
const VabKeelImg = Img;
const VabKeelText = Text;
export { VabKeel, VabKeelHeading, VabKeelImg, VabKeelText };
import VabMagnifier from "zx-magnifie";
export default VabMagnifier;
import ZxMarkdownEditor from "zx-markdown-editor";
import "zx-markdown-editor/dist/zx-markdown-editor.css";
const VabMarkdownEditor = ZxMarkdownEditor;
export default VabMarkdownEditor;
import { Custom, Flv, Hls, Mp4 } from "zx-player";
const VabPlayerMp4 = Mp4;
const VabPlayerHls = Hls;
const VabPlayerFlv = Flv;
const VabPlayerCustom = Custom;
export { VabPlayerMp4, VabPlayerHls, VabPlayerFlv, VabPlayerCustom };
import "zx-quill/dist/zx-quill.css";
import VabQuill from "zx-quill";
export default VabQuill;
import VabVerify from "zx-verify";
import "zx-verify/dist/zx-verify.css";
export default VabVerify;
import Vue from "vue";
import { RemixIcon } from "@/layouts/components";
Vue.component("vab-remix-icon", RemixIcon);
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);
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M19.913 14.529a31.977 31.977 0 00-.675-1.886l-.91-2.246c0-.026.012-.468.012-.696C18.34 5.86 16.507 2 12 2S5.66 5.86 5.66 9.7c0 .229.011.671.012.697l-.91 2.246a32.777 32.777 0 00-.675 1.886c-.86 2.737-.581 3.87-.369 3.895.455.054 1.771-2.06 1.771-2.06 0 1.224.637 2.822 2.016 3.976-.515.157-1.147.399-1.554.695-.365.267-.319.54-.253.65.289.481 4.955.307 6.303.157 1.347.15 6.014.324 6.302-.158.066-.11.112-.382-.253-.649-.407-.296-1.039-.538-1.555-.696 1.379-1.153 2.016-2.751 2.016-3.976 0 0 1.316 2.115 1.771 2.06.212-.025.49-1.157-.37-3.894"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M1 3h4l7 12 7-12h4L12 22 1 3zm8.667 0L12 7l2.333-4h4.035L12 14 5.632 3h4.035z"/></svg>
/**
* @copyright chuzhixin 1204505056@qq.com
* @description router全局配置,如有必要可分文件抽离,其中asyncRoutes只有在intelligence模式下才会用到,vip文档中已提供路由的基础图标与小清新图标的配置方案,请仔细阅读
*/
import Vue from "vue";
import VueRouter from "vue-router";
import Layout from "@/layouts";
import EmptyLayout from "@/layouts/EmptyLayout";
import { publicPath, routerMode } from "@/config/settings";
Vue.use(VueRouter);
export const constantRoutes = [
{
path: "/login",
component: () => import("@/views/login/index"),
hidden: true,
},
{
path: "/register",
component: () => import("@/views/register/index"),
hidden: true,
},
{
path: "/401",
name: "401",
component: () => import("@/views/401"),
hidden: true,
},
{
path: "/404",
name: "404",
component: () => import("@/views/404"),
hidden: true,
},
];
export const asyncRoutes = [
{
path: "/",
component: Layout,
redirect: "index",
children: [
{
path: "index",
name: "Index",
component: () => import("@/views/index/index"),
meta: {
title: "首页",
icon: "home",
affix: true,
},
},
],
},
{
path: "/personalCenter",
component: Layout,
hidden: true,
redirect: "personalCenter",
children: [
{
path: "personalCenter",
name: "PersonalCenter",
component: () => import("@/views/personalCenter/index"),
meta: {
title: "个人中心",
},
},
],
},
/* {
path: "/test",
component: Layout,
redirect: "noRedirect",
children: [
{
path: "test",
name: "Test",
component: () => import("@/views/test/index"),
meta: {
title: "test",
icon: "marker",
permissions: ["admin"],
},
},
],
}, */
{
path: "/personnelManagement",
component: Layout,
redirect: "noRedirect",
name: "PersonnelManagement",
meta: { title: "配置", icon: "users-cog", permissions: ["admin"] },
children: [
{
path: "userManagement",
name: "UserManagement",
component: () =>
import("@/views/personnelManagement/userManagement/index"),
meta: { title: "用户管理" },
},
{
path: "roleManagement",
name: "RoleManagement",
component: () =>
import("@/views/personnelManagement/roleManagement/index"),
meta: { title: "角色管理" },
},
{
path: "menuManagement",
name: "MenuManagement",
component: () =>
import("@/views/personnelManagement/menuManagement/index"),
meta: { title: "菜单管理", badge: "New" },
},
],
},
{
path: "/vab",
component: Layout,
redirect: "noRedirect",
name: "Vab",
alwaysShow: true,
meta: { title: "组件", icon: "box-open" },
children: [
{
path:
"https://github.com/chuzhixin/vue-admin-beautiful?utm_source=gold_browser_extension",
name: "ExternalLink",
meta: {
title: "外链",
target: "_blank",
permissions: ["admin", "editor"],
badge: "New",
},
},
{
path: "permissions",
name: "Permission",
component: () => import("@/views/vab/permissions/index"),
meta: {
title: "权限控制",
permissions: ["admin", "editor"],
},
},
{
path: "icon",
component: EmptyLayout,
redirect: "noRedirect",
name: "Icon",
meta: {
title: "图标",
permissions: ["admin"],
},
children: [
{
path: "awesomeIcon",
name: "AwesomeIcon",
component: () => import("@/views/vab/icon/index"),
meta: { title: "常规图标" },
},
{
path: "remixIcon",
name: "RemixIcon",
component: () => import("@/views/vab/icon/remixIcon"),
meta: { title: "小清新图标" },
},
{
path: "colorfulIcon",
name: "ColorfulIcon",
component: () => import("@/views/vab/icon/colorfulIcon"),
meta: { title: "多彩图标" },
},
],
},
{
path: "table",
component: EmptyLayout,
redirect: "noRedirect",
name: "Table",
meta: {
title: "表格",
permissions: ["admin"],
},
children: [
{
path: "comprehensiveTable",
name: "ComprehensiveTable",
component: () => import("@/views/vab/table/index"),
meta: { title: "综合表格" },
},
{
path: "inlineEditTable",
name: "InlineEditTable",
component: () => import("@/views/vab/table/inlineEditTable"),
meta: { title: "行内编辑" },
},
],
},
{
path: "map",
component: () => import("@/views/vab/map/index"),
name: "Map",
meta: {
title: "地图",
permissions: ["admin"],
},
},
{
path: "webSocket",
name: "WebSocket",
component: () => import("@/views/vab/webSocket/index"),
meta: { title: "webSocket", permissions: ["admin"] },
},
{
path: "form",
name: "Form",
component: () => import("@/views/vab/form/index"),
meta: { title: "表单", permissions: ["admin"] },
},
{
path: "element",
name: "Element",
component: () => import("@/views/vab/element/index"),
meta: { title: "常用组件", permissions: ["admin"] },
},
{
path: "tree",
name: "Tree",
component: () => import("@/views/vab/tree/index"),
meta: { title: "树", permissions: ["admin"] },
},
{
path: "card",
name: "Card",
component: () => import("@/views/vab/card/index"),
meta: { title: "卡片", permissions: ["admin"] },
},
{
path: "betterScroll",
name: "BetterScroll",
component: () => import("@/views/vab/betterScroll/index"),
meta: {
title: "滚动侦测",
permissions: ["admin"],
},
},
{
path: "verify",
name: "Verify",
component: () => import("@/views/vab/verify/index"),
meta: { title: "验证码", permissions: ["admin"] },
},
{
path: "menu1",
component: () => import("@/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: () => import("@/views/vab/nested/menu1/menu1-1/index"),
children: [
{
path: "menu1-1-1",
name: "Menu1-1-1",
meta: { title: "嵌套路由 1-1-1" },
component: () =>
import("@/views/vab/nested/menu1/menu1-1/menu1-1-1/index"),
},
],
},
],
},
{
path: "magnifier",
name: "Magnifier",
component: () => import("@/views/vab/magnifier/index"),
meta: { title: "放大镜", permissions: ["admin"] },
},
{
path: "echarts",
name: "Echarts",
component: () => import("@/views/vab/echarts/index"),
meta: { title: "图表", permissions: ["admin"] },
},
{
path: "loading",
name: "Loading",
component: () => import("@/views/vab/loading/index"),
meta: { title: "loading", permissions: ["admin"] },
},
{
path: "player",
name: "Player",
component: () => import("@/views/vab/player/index"),
meta: { title: "视频播放器", permissions: ["admin"] },
},
{
path: "markdownEditor",
name: "MarkdownEditor",
component: () => import("@/views/vab/markdownEditor/index"),
meta: { title: "markdown编辑器", permissions: ["admin"] },
},
{
path: "editor",
name: "Editor",
component: () => import("@/views/vab/editor/index"),
meta: {
title: "富文本编辑器",
permissions: ["admin"],
badge: "New",
},
},
{
path: "qrCode",
name: "QrCode",
component: () => import("@/views/vab/qrCode/index"),
meta: { title: "二维码", permissions: ["admin"] },
},
{
path: "backToTop",
name: "BackToTop",
component: () => import("@/views/vab/backToTop/index"),
meta: { title: "返回顶部", permissions: ["admin"] },
},
{
path: "lodash",
name: "Lodash",
component: () => import("@/views/vab/lodash/index"),
meta: { title: "lodash", permissions: ["admin"] },
},
{
path: "imgComparison",
name: "ImgComparison",
component: () => import("@/views/vab/imgComparison/index"),
meta: { title: "图像拖拽比对", permissions: ["admin"] },
},
{
path: "codeGenerator",
name: "CodeGenerator",
component: () => import("@/views/vab/codeGenerator/index"),
meta: { title: "代码生成机", permissions: ["admin"] },
},
{
path: "markdown",
name: "Markdown",
component: () => import("@/views/vab/markdown/index"),
meta: { title: "markdown阅读器", permissions: ["admin"] },
},
{
path: "smallComponents",
name: "SmallComponents",
component: () => import("@/views/vab/smallComponents/index"),
meta: { title: "小组件", permissions: ["admin"] },
},
{
path: "upload",
name: "Upload",
component: () => import("@/views/vab/upload/index"),
meta: { title: "上传", permissions: ["admin"] },
},
{
path: "sticky",
name: "Sticky",
component: () => import("@/views/vab/sticky/index"),
meta: { title: "sticky吸附", permissions: ["admin"] },
},
{
path: "log",
name: "Log",
component: () => import("@/views/vab/errorLog/index"),
meta: { title: "错误日志模拟", permissions: ["admin"] },
},
{
path: "more",
name: "More",
component: () => import("@/views/vab/more/index"),
meta: { title: "更多组件", permissions: ["admin"] },
},
{
path: "blacklist",
name: "Blacklist",
component: () => import("@/views/vab/blacklist/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: () => import("@/views/mall/pay/index"),
meta: {
title: "支付",
noKeepAlive: true,
},
children: null,
},
{
path: "goodsList",
name: "GoodsList",
component: () => import("@/views/mall/goodsList/index"),
meta: {
title: "商品列表",
},
},
{
path: "goodsDetail",
name: "GoodsDetail",
component: () => import("@/views/mall/goodsDetail/index"),
meta: {
title: "商品详情",
},
},
],
},
{
path: "/error",
component: EmptyLayout,
redirect: "noRedirect",
name: "Error",
meta: { title: "错误页", icon: "bug" },
children: [
{
path: "401",
name: "Error401",
component: () => import("@/views/401"),
meta: { title: "401" },
},
{
path: "404",
name: "Error404",
component: () => import("@/views/404"),
meta: { title: "404" },
},
],
},
{
path: "*",
redirect: "/404",
hidden: true,
},
];
const router = new VueRouter({
base: publicPath,
mode: routerMode,
scrollBehavior: () => ({
y: 0,
}),
routes: constantRoutes,
});
//注释的地方是允许路由重复点击,如果你觉得框架路由跳转规范太过严格可选择放开
/* const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location, onResolve, onReject) {
if (onResolve || onReject)
return originalPush.call(this, location, onResolve, onReject);
return originalPush.call(this, location).catch((err) => err);
}; */
export function resetRouter() {
router.matcher = new VueRouter({
base: publicPath,
mode: routerMode,
scrollBehavior: () => ({
y: 0,
}),
routes: constantRoutes,
}).matcher;
}
export default router;
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 导入所有 vuex 模块,自动加入namespaced:true,用于解决vuex命名冲突,请勿修改。
*/
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
const files = require.context("./modules", false, /\.js$/);
const modules = {};
files.keys().forEach((key) => {
modules[key.replace(/(\.\/|\.js)/g, "")] = files(key).default;
});
Object.keys(modules).forEach((key) => {
modules[key]["namespaced"] = true;
});
const store = new Vuex.Store({
modules,
});
export default store;
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 异常捕获的状态拦截,请勿修改
*/
const state = { errorLogs: [] };
const getters = {
errorLogs: (state) => state.errorLogs,
};
const mutations = {
addErrorLog(state, errorLog) {
state.errorLogs.push(errorLog);
},
clearErrorLog: (state) => {
state.errorLogs.splice(0);
},
};
const actions = {
addErrorLog({ commit }, errorLog) {
commit("addErrorLog", errorLog);
},
clearErrorLog({ commit }) {
commit("clearErrorLog");
},
};
export default { state, getters, mutations, actions };
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 路由拦截状态管理,目前两种模式:all模式与intelligence模式,其中partialRoutes是菜单暂未使用
*/
import { asyncRoutes, constantRoutes } from "@/router";
import { getRouterList } from "@/api/router";
import { filterAllRoutes, filterAsyncRoutes } from "@/utils/handleRoutes";
const state = { routes: [], partialRoutes: [] };
const getters = {
routes: (state) => state.routes,
partialRoutes: (state) => state.partialRoutes,
};
const mutations = {
setRoutes(state, routes) {
state.routes = constantRoutes.concat(routes);
},
setAllRoutes(state, routes) {
state.routes = constantRoutes.concat(routes);
},
setPartialRoutes(state, routes) {
state.partialRoutes = constantRoutes.concat(routes);
},
};
const actions = {
async setRoutes({ commit }, permissions) {
//开源版只过滤动态路由permissions,admin不再默认拥有全部权限
const finallyAsyncRoutes = await filterAsyncRoutes(
[...asyncRoutes],
permissions
);
commit("setRoutes", finallyAsyncRoutes);
return finallyAsyncRoutes;
},
async setAllRoutes({ commit }) {
let { data } = await getRouterList();
data.push({ path: "*", redirect: "/404", hidden: true });
let accessRoutes = filterAllRoutes(data);
commit("setAllRoutes", accessRoutes);
return accessRoutes;
},
setPartialRoutes({ commit }, accessRoutes) {
commit("setPartialRoutes", accessRoutes);
return accessRoutes;
},
};
export default { state, getters, mutations, actions };
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 所有全局配置的状态管理,如无必要请勿修改
*/
import defaultSettings from "@/config/settings";
const { tagsBar, logo, layout, header, themeBar, skeleton } = defaultSettings;
const theme =
JSON.parse(localStorage.getItem("vue-admin-beautiful-theme")) || "";
const state = {
tagsBar: theme.tagsBar || tagsBar,
logo,
collapse: false,
layout: theme.layout || layout,
header: theme.header || header,
skeleton,
device: "desktop",
themeBar,
};
const getters = {
collapse: (state) => state.collapse,
device: (state) => state.device,
header: (state) => state.header,
layout: (state) => state.layout,
logo: (state) => state.logo,
tagsBar: (state) => state.tagsBar,
themeBar: (state) => state.themeBar,
skeleton: (state) => state.skeleton,
};
const mutations = {
changeLayout: (state, layout) => {
if (layout) state.layout = layout;
},
changeHeader: (state, header) => {
if (header) state.header = header;
},
changeTagsBar: (state, tagsBar) => {
if (tagsBar) state.tagsBar = tagsBar;
},
changeCollapse: (state) => {
state.collapse = !state.collapse;
},
foldSideBar: (state) => {
state.collapse = true;
},
openSideBar: (state) => {
state.collapse = false;
},
toggleDevice: (state, device) => {
state.device = device;
},
};
const actions = {
changeLayout({ commit }, layout) {
commit("changeLayout", layout);
},
changeHeader({ commit }, header) {
commit("changeHeader", header);
},
changeTagsBar({ commit }, tagsBar) {
commit("changeTagsBar", tagsBar);
},
changeCollapse({ commit }) {
commit("changeCollapse");
},
foldSideBar({ commit }) {
commit("foldSideBar");
},
openSideBar({ commit }) {
commit("openSideBar");
},
toggleDevice({ commit }, device) {
commit("toggleDevice", device);
},
};
export default { state, getters, mutations, actions };
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 代码生成机状态管理
*/
const state = { srcCode: "" };
const getters = {
srcTableCode: (state) => state.srcCode,
};
const mutations = {
setTableCode(state, srcCode) {
state.srcCode = srcCode;
},
};
const actions = {
setTableCode({ commit }, srcCode) {
commit("setTableCode", srcCode);
},
};
export default { state, getters, mutations, actions };
/**
* @copyright chuzhixin 1204505056@qq.com
* @description tagsBar多标签页逻辑,前期借鉴了很多开源项目发现都有个共同的特点很繁琐并不符合框架设计的初衷,后来在github用户cyea的启发下完成了重构,请勿修改
*/
const state = {
visitedRoutes: [],
};
const getters = {
visitedRoutes: (state) => state.visitedRoutes,
};
const mutations = {
addVisitedRoute(state, route) {
if (state.visitedRoutes.some((item) => item.path === route.path)) return;
state.visitedRoutes.push(Object.assign({}, route));
},
delVisitedRoute(state, route) {
state.visitedRoutes.forEach((item, index) => {
if (item.path === route.path) {
state.visitedRoutes.splice(index, 1);
}
});
},
delOthersVisitedRoute(state, route) {
state.visitedRoutes = state.visitedRoutes.filter((item) => {
return item.meta.affix || item.path === route.path;
});
},
delLeftVisitedRoute(state, route) {
let index = state.visitedRoutes.length;
state.visitedRoutes = state.visitedRoutes.filter((item) => {
if (item.name === route.name) {
index = state.visitedRoutes.indexOf(item);
}
return item.meta.affix || index <= state.visitedRoutes.indexOf(item);
});
},
delRightVisitedRoute(state, route) {
let index = state.visitedRoutes.length;
state.visitedRoutes = state.visitedRoutes.filter((item) => {
if (item.name === route.name) {
index = state.visitedRoutes.indexOf(item);
}
return item.meta.affix || index >= state.visitedRoutes.indexOf(item);
});
},
delAllVisitedRoutes(state) {
state.visitedRoutes = state.visitedRoutes.filter((item) => item.meta.affix);
},
updateVisitedRoute(state, route) {
state.visitedRoutes.forEach((item) => {
if (item.path === route.path) {
item = Object.assign(item, route);
}
});
},
};
const actions = {
addVisitedRoute({ commit }, route) {
commit("addVisitedRoute", route);
},
async delRoute({ dispatch, state }, route) {
await dispatch("delVisitedRoute", route);
return {
visitedRoutes: [...state.visitedRoutes],
};
},
delVisitedRoute({ commit, state }, route) {
commit("delVisitedRoute", route);
return [...state.visitedRoutes];
},
async delOthersRoutes({ dispatch, state }, route) {
await dispatch("delOthersVisitedRoute", route);
return {
visitedRoutes: [...state.visitedRoutes],
};
},
async delLeftRoutes({ dispatch, state }, route) {
await dispatch("delLeftVisitedRoute", route);
return {
visitedRoutes: [...state.visitedRoutes],
};
},
async delRightRoutes({ dispatch, state }, route) {
await dispatch("delRightVisitedRoute", route);
return {
visitedRoutes: [...state.visitedRoutes],
};
},
delOthersVisitedRoute({ commit, state }, route) {
commit("delOthersVisitedRoute", route);
return [...state.visitedRoutes];
},
delLeftVisitedRoute({ commit, state }, route) {
commit("delLeftVisitedRoute", route);
return [...state.visitedRoutes];
},
delRightVisitedRoute({ commit, state }, route) {
commit("delRightVisitedRoute", route);
return [...state.visitedRoutes];
},
async delAllRoutes({ dispatch, state }, route) {
await dispatch("delAllVisitedRoutes", route);
return {
visitedRoutes: [...state.visitedRoutes],
};
},
delAllVisitedRoutes({ commit, state }) {
commit("delAllVisitedRoutes");
return [...state.visitedRoutes];
},
updateVisitedRoute({ commit }, route) {
commit("updateVisitedRoute", route);
},
};
export default { state, getters, mutations, actions };
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 登录、获取用户信息、退出登录、清除accessToken逻辑,不建议修改
*/
import Vue from "vue";
import { getUserInfo, login, logout } from "@/api/user";
import {
getAccessToken,
removeAccessToken,
setAccessToken,
} from "@/utils/accessToken";
import { resetRouter } from "@/router";
import { title, tokenName } from "@/config/settings";
const state = {
accessToken: getAccessToken(),
username: "",
avatar: "",
permissions: [],
};
const getters = {
accessToken: (state) => state.accessToken,
username: (state) => state.username,
avatar: (state) => state.avatar,
permissions: (state) => state.permissions,
};
const mutations = {
setAccessToken(state, accessToken) {
state.accessToken = accessToken;
setAccessToken(accessToken);
},
setUsername(state, username) {
state.username = username;
},
setAvatar(state, avatar) {
state.avatar = avatar;
},
setPermissions(state, permissions) {
state.permissions = permissions;
},
};
const actions = {
setPermissions({ commit }, permissions) {
commit("setPermissions", permissions);
},
async login({ commit }, userInfo) {
const { data } = await login(userInfo);
const accessToken = data[tokenName];
if (accessToken) {
commit("setAccessToken", accessToken);
const hour = new Date().getHours();
const thisTime =
hour < 8
? "早上好"
: hour <= 11
? "上午好"
: hour <= 13
? "中午好"
: hour < 18
? "下午好"
: "晚上好";
Vue.prototype.$baseNotify(`欢迎登录${title}`, `${thisTime}!`);
} else {
Vue.prototype.$baseMessage(
`登录接口异常,未正确返回${tokenName}...`,
"error"
);
}
},
async getUserInfo({ commit, state }) {
const { data } = await getUserInfo(state.accessToken);
if (!data) {
Vue.prototype.$baseMessage("验证失败,请重新登录...", "error");
return false;
}
let { permissions, username, avatar } = data;
if (permissions && username && Array.isArray(permissions)) {
commit("setPermissions", permissions);
commit("setUsername", username);
commit("setAvatar", avatar);
return permissions;
} else {
Vue.prototype.$baseMessage("用户信息接口异常", "error");
return false;
}
},
async logout({ dispatch }) {
await logout(state.accessToken);
await dispatch("resetAccessToken");
await resetRouter();
},
resetAccessToken({ commit }) {
commit("setPermissions", []);
commit("setAccessToken", "");
removeAccessToken();
},
};
export default { state, getters, mutations, actions };
@charset "utf-8";
/* Transition
-------------------------- */
$--all-transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
$--fade-transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
$--fade-linear-transition: opacity 200ms linear;
$--md-fade-transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1),
opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
$--border-transition-base: border-color 0.2s
cubic-bezier(0.645, 0.045, 0.355, 1);
$--color-transition-base: color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
/* Color
-------------------------- */
/// color|1|Brand Color|0
$--color-primary: $base-color-blue;
/// color|1|Background Color|4
$--color-white: #fff;
/// color|1|Background Color|4
$--color-black: #000;
$--color-primary-light-1: mix($--color-white, $--color-primary, 10%);
/* 53a8ff */
$--color-primary-light-2: mix($--color-white, $--color-primary, 20%);
/* 66b1ff */
$--color-primary-light-3: mix($--color-white, $--color-primary, 30%);
/* 79bbff */
$--color-primary-light-4: mix($--color-white, $--color-primary, 40%);
/* 8cc5ff */
$--color-primary-light-5: mix($--color-white, $--color-primary, 50%);
/* a0cfff */
$--color-primary-light-6: mix($--color-white, $--color-primary, 60%);
/* b3d8ff */
$--color-primary-light-7: mix($--color-white, $--color-primary, 70%);
/* c6e2ff */
$--color-primary-light-8: mix($--color-white, $--color-primary, 80%);
/* d9ecff */
$--color-primary-light-9: mix($--color-white, $--color-primary, 90%);
/* ecf5ff */
/// color|1|Functional Color|1
$--color-success: $base-color-green;
/// color|1|Functional Color|1
$--color-warning: $base-color-yellow;
/// color|1|Functional Color|1
$--color-danger: $base-color-red;
/// color|1|Functional Color|1
$--color-info: #909399;
$--color-success-light: mix($--color-white, $--color-success, 80%);
$--color-warning-light: mix($--color-white, $--color-warning, 80%);
$--color-danger-light: mix($--color-white, $--color-danger, 80%);
$--color-info-light: mix($--color-white, $--color-info, 80%);
$--color-success-lighter: mix($--color-white, $--color-success, 90%);
$--color-warning-lighter: mix($--color-white, $--color-warning, 90%);
$--color-danger-lighter: mix($--color-white, $--color-danger, 90%);
$--color-info-lighter: mix($--color-white, $--color-info, 90%);
/// color|1|Font Color|2
$--color-text-primary: #303133;
/// color|1|Font Color|2
$--color-text-regular: #606266;
/// color|1|Font Color|2
$--color-text-secondary: #909399;
/// color|1|Font Color|2
$--color-text-placeholder: #c0c4cc;
/// color|1|Border Color|3
$--border-color-base: #dcdfe6;
/// color|1|Border Color|3
$--border-color-light: #e4e7ed;
/// color|1|Border Color|3
$--border-color-lighter: #ebeef5;
/// color|1|Border Color|3
$--border-color-extra-light: #f2f6fc;
// Background
/// color|1|Background Color|4
$--background-color-base: #f5f7fa;
/* Link
-------------------------- */
$--link-color: $--color-primary-light-2;
$--link-hover-color: $--color-primary;
/* Border
-------------------------- */
$--border-width-base: 1px;
$--border-style-base: solid;
$--border-color-hover: $--color-text-placeholder;
$--border-base: $--border-width-base $--border-style-base $--border-color-base;
/// borderRadius|1|Radius|0
$--border-radius-base: $base-border-radius;
/// borderRadius|1|Radius|0
$--border-radius-small: $base-border-radius;
/// borderRadius|1|Radius|0
$--border-radius-circle: 100%;
/// borderRadius|1|Radius|0
$--border-radius-zero: 0;
// Box-shadow
/// boxShadow|1|Shadow|1
$--box-shadow-base: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
// boxShadow|1|Shadow|1
$--box-shadow-dark: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.12);
/// boxShadow|1|Shadow|1
$--box-shadow-light: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
/* Fill
-------------------------- */
$--fill-base: $--color-white;
/* Typography
-------------------------- */
$--font-path: "~element-ui/lib/theme-chalk/fonts";
$--font-display: "auto";
/// fontSize|1|Font Size|0
$--font-size-extra-large: 20px;
/// fontSize|1|Font Size|0
$--font-size-large: 18px;
/// fontSize|1|Font Size|0
$--font-size-medium: 16px;
/// fontSize|1|Font Size|0
$--font-size-base: 14px;
/// fontSize|1|Font Size|0
$--font-size-small: 13px;
/// fontSize|1|Font Size|0
$--font-size-extra-small: 12px;
/// fontWeight|1|Font Weight|1
$--font-weight-primary: 500;
/// fontWeight|1|Font Weight|1
$--font-weight-secondary: 100;
/// fontLineHeight|1|Line Height|2
$--font-line-height-primary: 24px;
/// fontLineHeight|1|Line Height|2
$--font-line-height-secondary: 16px;
$--font-color-disabled-base: #bbb;
/* Size
-------------------------- */
$--size-base: 14px;
/* z-index
-------------------------- */
$--index-normal: 1;
$--index-top: 1000;
$--index-popper: 2000;
/* Disable base
-------------------------- */
$--disabled-fill-base: $--background-color-base;
$--disabled-color-base: $--color-text-placeholder;
$--disabled-border-base: $--border-color-light;
/* Icon
-------------------------- */
$--icon-color: #666;
$--icon-color-base: $--color-info;
/* Checkbox
-------------------------- */
/// fontSize||Font|1
$--checkbox-font-size: 14px;
/// fontWeight||Font|1
$--checkbox-font-weight: $--font-weight-primary;
/// color||Color|0
$--checkbox-font-color: $--color-text-regular;
$--checkbox-input-height: 14px;
$--checkbox-input-width: 14px;
/// borderRadius||Border|2
$--checkbox-border-radius: $--border-radius-small;
/// color||Color|0
$--checkbox-background-color: $--color-white;
$--checkbox-input-border: $--border-base;
/// color||Color|0
$--checkbox-disabled-border-color: $--border-color-base;
$--checkbox-disabled-input-fill: #edf2fc;
$--checkbox-disabled-icon-color: $--color-text-placeholder;
$--checkbox-disabled-checked-input-fill: $--border-color-extra-light;
$--checkbox-disabled-checked-input-border-color: $--border-color-base;
$--checkbox-disabled-checked-icon-color: $--color-text-placeholder;
/// color||Color|0
$--checkbox-checked-font-color: $--color-primary;
$--checkbox-checked-input-border-color: $--color-primary;
/// color||Color|0
$--checkbox-checked-background-color: $--color-primary;
$--checkbox-checked-icon-color: $--fill-base;
$--checkbox-input-border-color-hover: $--color-primary;
/// height||Other|4
$--checkbox-bordered-height: 40px;
/// padding||Spacing|3
$--checkbox-bordered-padding: 9px 20px 9px 10px;
/// padding||Spacing|3
$--checkbox-bordered-medium-padding: 7px 20px 7px 10px;
/// padding||Spacing|3
$--checkbox-bordered-small-padding: 5px 15px 5px 10px;
/// padding||Spacing|3
$--checkbox-bordered-mini-padding: 3px 15px 3px 10px;
$--checkbox-bordered-medium-input-height: 14px;
$--checkbox-bordered-medium-input-width: 14px;
/// height||Other|4
$--checkbox-bordered-medium-height: 36px;
$--checkbox-bordered-small-input-height: 12px;
$--checkbox-bordered-small-input-width: 12px;
/// height||Other|4
$--checkbox-bordered-small-height: 32px;
$--checkbox-bordered-mini-input-height: 12px;
$--checkbox-bordered-mini-input-width: 12px;
/// height||Other|4
$--checkbox-bordered-mini-height: 28px;
/// color||Color|0
$--checkbox-button-checked-background-color: $--color-primary;
/// color||Color|0
$--checkbox-button-checked-font-color: $--color-white;
/// color||Color|0
$--checkbox-button-checked-border-color: $--color-primary;
/* Radio
-------------------------- */
/// fontSize||Font|1
$--radio-font-size: $--font-size-base;
/// fontWeight||Font|1
$--radio-font-weight: $--font-weight-primary;
/// color||Color|0
$--radio-font-color: $--color-text-regular;
$--radio-input-height: 14px;
$--radio-input-width: 14px;
/// borderRadius||Border|2
$--radio-input-border-radius: $--border-radius-circle;
/// color||Color|0
$--radio-input-background-color: $--color-white;
$--radio-input-border: $--border-base;
/// color||Color|0
$--radio-input-border-color: $--border-color-base;
/// color||Color|0
$--radio-icon-color: $--color-white;
$--radio-disabled-input-border-color: $--disabled-border-base;
$--radio-disabled-input-fill: $--disabled-fill-base;
$--radio-disabled-icon-color: $--disabled-fill-base;
$--radio-disabled-checked-input-border-color: $--disabled-border-base;
$--radio-disabled-checked-input-fill: $--disabled-fill-base;
$--radio-disabled-checked-icon-color: $--color-text-placeholder;
/// color||Color|0
$--radio-checked-font-color: $--color-primary;
/// color||Color|0
$--radio-checked-input-border-color: $--color-primary;
/// color||Color|0
$--radio-checked-input-background-color: $--color-white;
/// color||Color|0
$--radio-checked-icon-color: $--color-primary;
$--radio-input-border-color-hover: $--color-primary;
$--radio-bordered-height: 40px;
$--radio-bordered-padding: 12px 20px 0 10px;
$--radio-bordered-medium-padding: 10px 20px 0 10px;
$--radio-bordered-small-padding: 8px 15px 0 10px;
$--radio-bordered-mini-padding: 6px 15px 0 10px;
$--radio-bordered-medium-input-height: 14px;
$--radio-bordered-medium-input-width: 14px;
$--radio-bordered-medium-height: 36px;
$--radio-bordered-small-input-height: 12px;
$--radio-bordered-small-input-width: 12px;
$--radio-bordered-small-height: 32px;
$--radio-bordered-mini-input-height: 12px;
$--radio-bordered-mini-input-width: 12px;
$--radio-bordered-mini-height: 28px;
/// fontSize||Font|1
$--radio-button-font-size: $--font-size-base;
/// color||Color|0
$--radio-button-checked-background-color: $--color-primary;
/// color||Color|0
$--radio-button-checked-font-color: $--color-white;
/// color||Color|0
$--radio-button-checked-border-color: $--color-primary;
$--radio-button-disabled-checked-fill: $--border-color-extra-light;
/* Select
-------------------------- */
$--select-border-color-hover: $--border-color-hover;
$--select-disabled-border: $--disabled-border-base;
/// fontSize||Font|1
$--select-font-size: $--font-size-base;
$--select-close-hover-color: $--color-text-secondary;
$--select-input-color: $--color-text-placeholder;
$--select-multiple-input-color: #666;
/// color||Color|0
$--select-input-focus-border-color: $--color-primary;
/// fontSize||Font|1
$--select-input-font-size: 14px;
$--select-option-color: $--color-text-regular;
$--select-option-disabled-color: $--color-text-placeholder;
$--select-option-disabled-background: $--color-white;
/// height||Other|4
$--select-option-height: 34px;
$--select-option-hover-background: $--background-color-base;
/// color||Color|0
$--select-option-selected-font-color: $--color-primary;
$--select-option-selected-hover: $--background-color-base;
$--select-group-color: $--color-info;
$--select-group-height: 30px;
$--select-group-font-size: 12px;
$--select-dropdown-background: $--color-white;
$--select-dropdown-shadow: $--box-shadow-light;
$--select-dropdown-empty-color: #999;
/// height||Other|4
$--select-dropdown-max-height: 274px;
$--select-dropdown-padding: 6px 0;
$--select-dropdown-empty-padding: 10px 0;
$--select-dropdown-border: solid 1px $--border-color-light;
/* Alert
-------------------------- */
$--alert-padding: 8px 16px;
/// borderRadius||Border|2
$--alert-border-radius: $--border-radius-base;
/// fontSize||Font|1
$--alert-title-font-size: 13px;
/// fontSize||Font|1
$--alert-description-font-size: 12px;
/// fontSize||Font|1
$--alert-close-font-size: 12px;
/// fontSize||Font|1
$--alert-close-customed-font-size: 13px;
$--alert-success-color: $--color-success-lighter;
$--alert-info-color: $--color-info-lighter;
$--alert-warning-color: $--color-warning-lighter;
$--alert-danger-color: $--color-danger-lighter;
/// height||Other|4
$--alert-icon-size: 16px;
/// height||Other|4
$--alert-icon-large-size: 28px;
/* MessageBox
-------------------------- */
/// color||Color|0
$--messagebox-title-color: $--color-text-primary;
$--msgbox-width: 420px;
$--msgbox-border-radius: $--border-radius-base;
/// fontSize||Font|1
$--messagebox-font-size: $--font-size-large;
/// fontSize||Font|1
$--messagebox-content-font-size: $--font-size-base;
/// color||Color|0
$--messagebox-content-color: $--color-text-regular;
/// fontSize||Font|1
$--messagebox-error-font-size: 12px;
$--msgbox-padding-primary: 15px;
/// color||Color|0
$--messagebox-success-color: $--color-success;
/// color||Color|0
$--messagebox-info-color: $--color-info;
/// color||Color|0
$--messagebox-warning-color: $--color-warning;
/// color||Color|0
$--messagebox-danger-color: $--color-danger;
/* Message
-------------------------- */
$--message-shadow: $--box-shadow-base;
$--message-min-width: 380px;
$--message-background-color: #edf2fc;
$--message-padding: 15px 15px 15px 20px;
/// color||Color|0
$--message-close-icon-color: $--color-text-placeholder;
/// height||Other|4
$--message-close-size: 16px;
/// color||Color|0
$--message-close-hover-color: $--color-text-secondary;
/// color||Color|0
$--message-success-font-color: $--color-success;
/// color||Color|0
$--message-info-font-color: $--color-info;
/// color||Color|0
$--message-warning-font-color: $--color-warning;
/// color||Color|0
$--message-danger-font-color: $--color-danger;
/* Notification
-------------------------- */
$--notification-width: 330px;
/// padding||Spacing|3
$--notification-padding: 14px 26px 14px 13px;
$--notification-radius: 8px;
$--notification-shadow: $--box-shadow-light;
/// color||Color|0
$--notification-border-color: $--border-color-lighter;
$--notification-icon-size: 24px;
$--notification-close-font-size: $--message-close-size;
$--notification-group-margin-left: 13px;
$--notification-group-margin-right: 8px;
/// fontSize||Font|1
$--notification-content-font-size: $--font-size-base;
/// color||Color|0
$--notification-content-color: $--color-text-regular;
/// fontSize||Font|1
$--notification-title-font-size: 16px;
/// color||Color|0
$--notification-title-color: $--color-text-primary;
/// color||Color|0
$--notification-close-color: $--color-text-secondary;
/// color||Color|0
$--notification-close-hover-color: $--color-text-regular;
/// color||Color|0
$--notification-success-icon-color: $--color-success;
/// color||Color|0
$--notification-info-icon-color: $--color-info;
/// color||Color|0
$--notification-warning-icon-color: $--color-warning;
/// color||Color|0
$--notification-danger-icon-color: $--color-danger;
/* Input
-------------------------- */
$--input-font-size: $--font-size-base;
/// color||Color|0
$--input-font-color: $--color-text-regular;
/// height||Other|4
$--input-width: 140px;
/// height||Other|4
$--input-height: 40px;
$--input-border: $--border-base;
$--input-border-color: $--border-color-base;
/// borderRadius||Border|2
$--input-border-radius: $--border-radius-base;
$--input-border-color-hover: $--border-color-hover;
/// color||Color|0
$--input-background-color: $--color-white;
$--input-fill-disabled: $--disabled-fill-base;
$--input-color-disabled: $--font-color-disabled-base;
/// color||Color|0
$--input-icon-color: $--color-text-placeholder;
/// color||Color|0
$--input-placeholder-color: $--color-text-placeholder;
$--input-max-width: 314px;
$--input-hover-border: $--border-color-hover;
$--input-clear-hover-color: $--color-text-secondary;
$--input-focus-border: $--color-primary;
$--input-focus-fill: $--color-white;
$--input-disabled-fill: $--disabled-fill-base;
$--input-disabled-border: $--disabled-border-base;
$--input-disabled-color: $--disabled-color-base;
$--input-disabled-placeholder-color: $--color-text-placeholder;
/// fontSize||Font|1
$--input-medium-font-size: 14px;
/// height||Other|4
$--input-medium-height: 36px;
/// fontSize||Font|1
$--input-small-font-size: 13px;
/// height||Other|4
$--input-small-height: 32px;
/// fontSize||Font|1
$--input-mini-font-size: 12px;
/// height||Other|4
$--input-mini-height: 28px;
/* Cascader
-------------------------- */
/// color||Color|0
$--cascader-menu-font-color: $--color-text-regular;
/// color||Color|0
$--cascader-menu-selected-font-color: $--color-primary;
$--cascader-menu-fill: $--fill-base;
$--cascader-menu-font-size: $--font-size-base;
$--cascader-menu-radius: $--border-radius-base;
$--cascader-menu-border: solid 1px $--border-color-light;
$--cascader-menu-shadow: $--box-shadow-light;
$--cascader-node-background-hover: $--background-color-base;
$--cascader-node-color-disabled: $--color-text-placeholder;
$--cascader-color-empty: $--color-text-placeholder;
$--cascader-tag-background: #f0f2f5;
/* Group
-------------------------- */
$--group-option-flex: 0 0 (1/5) * 100%;
$--group-option-offset-bottom: 12px;
$--group-option-fill-hover: rgba($--color-black, 0.06);
$--group-title-color: $--color-black;
$--group-title-font-size: $--font-size-base;
$--group-title-width: 66px;
/* Tab
-------------------------- */
$--tab-font-size: $--font-size-base;
$--tab-border-line: 1px solid #e4e4e4;
$--tab-header-color-active: $--color-text-secondary;
$--tab-header-color-hover: $--color-text-regular;
$--tab-header-color: $--color-text-regular;
$--tab-header-fill-active: rgba($--color-black, 0.06);
$--tab-header-fill-hover: rgba($--color-black, 0.06);
$--tab-vertical-header-width: 90px;
$--tab-vertical-header-count-color: $--color-white;
$--tab-vertical-header-count-fill: $--color-text-secondary;
/* Button
-------------------------- */
/// fontSize||Font|1
$--button-font-size: $--font-size-base;
/// fontWeight||Font|1
$--button-font-weight: $--font-weight-primary;
/// borderRadius||Border|2
$--button-border-radius: $--border-radius-base;
/// padding||Spacing|3
$--button-padding-vertical: 12px;
/// padding||Spacing|3
$--button-padding-horizontal: 20px;
/// fontSize||Font|1
$--button-medium-font-size: $--font-size-base;
/// borderRadius||Border|2
$--button-medium-border-radius: $--border-radius-base;
/// padding||Spacing|3
$--button-medium-padding-vertical: 10px;
/// padding||Spacing|3
$--button-medium-padding-horizontal: 20px;
/// fontSize||Font|1
$--button-small-font-size: 12px;
$--button-small-border-radius: $--border-radius-base;
/// padding||Spacing|3
$--button-small-padding-vertical: 9px;
/// padding||Spacing|3
$--button-small-padding-horizontal: 15px;
/// fontSize||Font|1
$--button-mini-font-size: 12px;
$--button-mini-border-radius: $--border-radius-base;
/// padding||Spacing|3
$--button-mini-padding-vertical: 7px;
/// padding||Spacing|3
$--button-mini-padding-horizontal: 15px;
/// color||Color|0
$--button-default-font-color: $--color-text-regular;
/// color||Color|0
$--button-default-background-color: $--color-white;
/// color||Color|0
$--button-default-border-color: $--border-color-base;
/// color||Color|0
$--button-disabled-font-color: $--color-text-placeholder;
/// color||Color|0
$--button-disabled-background-color: $--color-white;
/// color||Color|0
$--button-disabled-border-color: $--border-color-lighter;
/// color||Color|0
$--button-primary-border-color: $--color-primary;
/// color||Color|0
$--button-primary-font-color: $--color-white;
/// color||Color|0
$--button-primary-background-color: $--color-primary;
/// color||Color|0
$--button-success-border-color: $--color-success;
/// color||Color|0
$--button-success-font-color: $--color-white;
/// color||Color|0
$--button-success-background-color: $--color-success;
/// color||Color|0
$--button-warning-border-color: $--color-warning;
/// color||Color|0
$--button-warning-font-color: $--color-white;
/// color||Color|0
$--button-warning-background-color: $--color-warning;
/// color||Color|0
$--button-danger-border-color: $--color-danger;
/// color||Color|0
$--button-danger-font-color: $--color-white;
/// color||Color|0
$--button-danger-background-color: $--color-danger;
/// color||Color|0
$--button-info-border-color: $--color-info;
/// color||Color|0
$--button-info-font-color: $--color-white;
/// color||Color|0
$--button-info-background-color: $--color-info;
$--button-hover-tint-percent: 20%;
$--button-active-shade-percent: 10%;
/* cascader
-------------------------- */
$--cascader-height: 200px;
/* Switch
-------------------------- */
/// color||Color|0
$--switch-on-color: $--color-primary;
/// color||Color|0
$--switch-off-color: $--border-color-base;
/// fontSize||Font|1
$--switch-font-size: $--font-size-base;
$--switch-core-border-radius: 10px;
// height||Other|4 TODO: width 代码写死的40px 所以下面这三个属性都没意义
$--switch-width: 40px;
// height||Other|4
$--switch-height: 20px;
// height||Other|4
$--switch-button-size: 16px;
/* Dialog
-------------------------- */
$--dialog-background-color: $--color-white;
$--dialog-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
/// fontSize||Font|1
$--dialog-title-font-size: $--font-size-large;
/// fontSize||Font|1
$--dialog-content-font-size: 14px;
/// fontLineHeight||LineHeight|2
$--dialog-font-line-height: $--font-line-height-primary;
/// padding||Spacing|3
$--dialog-padding-primary: 20px;
/* Table
-------------------------- */
/// color||Color|0
$--table-border-color: $--border-color-lighter;
$--table-border: 1px solid $--table-border-color;
/// color||Color|0
$--table-font-color: $--color-text-regular;
/// color||Color|0
$--table-header-font-color: $--color-text-secondary;
/// color||Color|0
$--table-row-hover-background-color: $--background-color-base;
$--table-current-row-background-color: $--color-primary-light-9;
/// color||Color|0
$--table-header-background-color: $--color-white;
$--table-fixed-box-shadow: 0 0 10px rgba(0, 0, 0, 0.12);
/* Pagination
-------------------------- */
/// fontSize||Font|1
$--pagination-font-size: 13px;
/// color||Color|0
$--pagination-background-color: $--color-white;
/// color||Color|0
$--pagination-font-color: $--color-text-primary;
$--pagination-border-radius: $--border-radius-base;
/// color||Color|0
$--pagination-button-color: $--color-text-primary;
/// height||Other|4
$--pagination-button-width: 35.5px;
/// height||Other|4
$--pagination-button-height: 28px;
/// color||Color|0
$--pagination-button-disabled-color: $--color-text-placeholder;
/// color||Color|0
$--pagination-button-disabled-background-color: $--color-white;
/// color||Color|0
$--pagination-hover-color: $--color-primary;
/* Popup
-------------------------- */
/// color||Color|0
$--popup-modal-background-color: $--color-black;
/// opacity||Other|1
$--popup-modal-opacity: 0.5;
/* Popover
-------------------------- */
/// color||Color|0
$--popover-background-color: $--color-white;
/// fontSize||Font|1
$--popover-font-size: $--font-size-base;
/// color||Color|0
$--popover-border-color: $--border-color-lighter;
$--popover-arrow-size: 6px;
/// padding||Spacing|3
$--popover-padding: 12px;
$--popover-padding-large: 18px 20px;
/// fontSize||Font|1
$--popover-title-font-size: 16px;
/// color||Color|0
$--popover-title-font-color: $--color-text-primary;
/* Tooltip
-------------------------- */
/// color|1|Color|0
$--tooltip-fill: $--color-text-primary;
/// color|1|Color|0
$--tooltip-color: $--color-white;
/// fontSize||Font|1
$--tooltip-font-size: 12px;
/// color||Color|0
$--tooltip-border-color: $--color-text-primary;
$--tooltip-arrow-size: 6px;
/// padding||Spacing|3
$--tooltip-padding: 10px;
/* Tag
-------------------------- */
/// color||Color|0
$--tag-info-color: $--color-info;
/// color||Color|0
$--tag-primary-color: $--color-primary;
/// color||Color|0
$--tag-success-color: $--color-success;
/// color||Color|0
$--tag-warning-color: $--color-warning;
/// color||Color|0
$--tag-danger-color: $--color-danger;
/// fontSize||Font|1
$--tag-font-size: 12px;
$--tag-border-radius: $--border-radius-base;
$--tag-padding: 0 10px;
/* Tree
-------------------------- */
/// color||Color|0
$--tree-node-hover-background-color: $--background-color-base;
/// color||Color|0
$--tree-font-color: $--color-text-regular;
/// color||Color|0
$--tree-expand-icon-color: $--color-text-placeholder;
/* Dropdown
-------------------------- */
$--dropdown-menu-box-shadow: $--box-shadow-light;
$--dropdown-menuItem-hover-fill: $--color-primary-light-9;
$--dropdown-menuItem-hover-color: $--link-color;
/* Badge
-------------------------- */
/// color||Color|0
$--badge-background-color: $--color-danger;
$--badge-radius: 10px;
/// fontSize||Font|1
$--badge-font-size: 12px;
/// padding||Spacing|3
$--badge-padding: 6px;
/// height||Other|4
$--badge-size: 18px;
/* Card
-------------------------- */
/// color||Color|0
$--card-border-color: $--border-color-lighter;
$--card-border-radius: $--border-radius-base;
/// padding||Spacing|3
$--card-padding: 20px;
/* Slider
-------------------------- */
/// color||Color|0
$--slider-main-background-color: $--color-primary;
/// color||Color|0
$--slider-runway-background-color: $--border-color-light;
$--slider-button-hover-color: mix($--color-primary, black, 97%);
$--slider-stop-background-color: $--color-white;
$--slider-disable-color: $--color-text-placeholder;
$--slider-margin: 16px 0;
$--slider-border-radius: $--border-radius-base;
/// height|1|Other|4
$--slider-height: 6px;
/// height||Other|4
$--slider-button-size: 16px;
$--slider-button-wrapper-size: 36px;
$--slider-button-wrapper-offset: -15px;
/* Steps
-------------------------- */
$--steps-border-color: $--disabled-border-base;
$--steps-border-radius: $--border-radius-base;
$--steps-padding: 20px;
/* Menu
-------------------------- */
/// fontSize||Font|1
$--menu-item-font-size: $--font-size-base;
/// color||Color|0
$--menu-item-font-color: $--color-text-primary;
/// color||Color|0
$--menu-background-color: $--color-white;
$--menu-item-hover-fill: $--color-primary-light-9;
/* Rate
-------------------------- */
$--rate-height: 20px;
/// fontSize||Font|1
$--rate-font-size: $--font-size-base;
/// height||Other|3
$--rate-icon-size: 18px;
/// margin||Spacing|2
$--rate-icon-margin: 6px;
$--rate-icon-color: $--color-text-placeholder;
/* DatePicker
-------------------------- */
$--datepicker-font-color: $--color-text-regular;
/// color|1|Color|0
$--datepicker-off-font-color: $--color-text-placeholder;
/// color||Color|0
$--datepicker-header-font-color: $--color-text-regular;
$--datepicker-icon-color: $--color-text-primary;
$--datepicker-border-color: $--disabled-border-base;
$--datepicker-inner-border-color: #e4e4e4;
/// color||Color|0
$--datepicker-inrange-background-color: $--border-color-extra-light;
/// color||Color|0
$--datepicker-inrange-hover-background-color: $--border-color-extra-light;
/// color||Color|0
$--datepicker-active-color: $--color-primary;
/// color||Color|0
$--datepicker-hover-font-color: $--color-primary;
$--datepicker-cell-hover-color: #fff;
/* Loading
-------------------------- */
/// height||Other|4
$--loading-spinner-size: 42px;
/// height||Other|4
$--loading-fullscreen-spinner-size: 50px;
/* Scrollbar
-------------------------- */
$--scrollbar-background-color: rgba($--color-text-secondary, 0.3);
$--scrollbar-hover-background-color: rgba($--color-text-secondary, 0.5);
/* Carousel
-------------------------- */
/// fontSize||Font|1
$--carousel-arrow-font-size: 12px;
$--carousel-arrow-size: 36px;
$--carousel-arrow-background: rgba(31, 45, 61, 0.11);
$--carousel-arrow-hover-background: rgba(31, 45, 61, 0.23);
/// width||Other|4
$--carousel-indicator-width: 30px;
/// height||Other|4
$--carousel-indicator-height: 2px;
$--carousel-indicator-padding-horizontal: 4px;
$--carousel-indicator-padding-vertical: 12px;
$--carousel-indicator-out-color: $--border-color-hover;
/* Collapse
-------------------------- */
/// color||Color|0
$--collapse-border-color: $--border-color-lighter;
/// height||Other|4
$--collapse-header-height: 48px;
/// color||Color|0
$--collapse-header-background-color: $--color-white;
/// color||Color|0
$--collapse-header-font-color: $--color-text-primary;
/// fontSize||Font|1
$--collapse-header-font-size: 13px;
/// color||Color|0
$--collapse-content-background-color: $--color-white;
/// fontSize||Font|1
$--collapse-content-font-size: 13px;
/// color||Color|0
$--collapse-content-font-color: $--color-text-primary;
/* Transfer
-------------------------- */
$--transfer-border-color: $--border-color-lighter;
$--transfer-border-radius: $--border-radius-base;
/// height||Other|4
$--transfer-panel-width: 200px;
/// height||Other|4
$--transfer-panel-header-height: 40px;
/// color||Color|0
$--transfer-panel-header-background-color: $--background-color-base;
/// height||Other|4
$--transfer-panel-footer-height: 40px;
/// height||Other|4
$--transfer-panel-body-height: 246px;
/// height||Other|4
$--transfer-item-height: 30px;
/// height||Other|4
$--transfer-filter-height: 32px;
/* Header
-------------------------- */
$--header-padding: 0 20px;
/* Footer
-------------------------- */
$--footer-padding: 0 20px;
/* Main
-------------------------- */
$--main-padding: 20px;
/* Timeline
-------------------------- */
$--timeline-node-size-normal: 12px;
$--timeline-node-size-large: 14px;
$--timeline-node-color: $--border-color-light;
/* Backtop
-------------------------- */
/// color||Color|0
$--backtop-background-color: $--color-white;
/// color||Color|0
$--backtop-font-color: $--color-primary;
/// color||Color|0
$--backtop-hover-background-color: $--border-color-extra-light;
/* Link
-------------------------- */
/// fontSize||Font|1
$--link-font-size: $--font-size-base;
/// fontWeight||Font|1
$--link-font-weight: $--font-weight-primary;
/// color||Color|0
$--link-default-font-color: $--color-text-regular;
/// color||Color|0
$--link-default-active-color: $--color-primary;
/// color||Color|0
$--link-disabled-font-color: $--color-text-placeholder;
/// color||Color|0
$--link-primary-font-color: $--color-primary;
/// color||Color|0
$--link-success-font-color: $--color-success;
/// color||Color|0
$--link-warning-font-color: $--color-warning;
/// color||Color|0
$--link-danger-font-color: $--color-danger;
/// color||Color|0
$--link-info-font-color: $--color-info;
/* Calendar
-------------------------- */
/// border||Other|4
$--calendar-border: $--table-border;
/// color||Other|4
$--calendar-selected-background-color: #f2f8fe;
$--calendar-cell-width: 85px;
/* Form
-------------------------- */
/// fontSize||Font|1
$--form-label-font-size: $--font-size-base;
/* Avatar
-------------------------- */
/// color||Color|0
$--avatar-font-color: #fff;
/// color||Color|0
$--avatar-background-color: #c0c4cc;
/// fontSize||Font Size|1
$--avatar-text-font-size: 14px;
/// fontSize||Font Size|1
$--avatar-icon-font-size: 18px;
/// borderRadius||Border|2
$--avatar-border-radius: $--border-radius-base;
/// size|1|Avatar Size|3
$--avatar-large-size: 40px;
/// size|1|Avatar Size|3
$--avatar-medium-size: 36px;
/// size|1|Avatar Size|3
$--avatar-small-size: 28px;
/* Break-point
-------------------------- */
$--sm: 768px;
$--md: 992px;
$--lg: 1200px;
$--xl: 1920px;
$--breakpoints: (
"xs": (
max-width: $--sm - 1,
),
"sm": (
min-width: $--sm,
),
"md": (
min-width: $--md,
),
"lg": (
min-width: $--lg,
),
"xl": (
min-width: $--xl,
),
);
$--breakpoints-spec: (
"xs-only": (
max-width: $--sm - 1,
),
"sm-and-up": (
min-width: $--sm,
),
"sm-only": "(min-width: #{$--sm}) and (max-width: #{$--md - 1})",
"sm-and-down": (
max-width: $--md - 1,
),
"md-and-up": (
min-width: $--md,
),
"md-only": "(min-width: #{$--md}) and (max-width: #{$--lg - 1})",
"md-and-down": (
max-width: $--lg - 1,
),
"lg-and-up": (
min-width: $--lg,
),
"lg-only": "(min-width: #{$--lg}) and (max-width: #{$--xl - 1})",
"lg-and-down": (
max-width: $--xl - 1,
),
"xl-only": (
min-width: $--xl,
),
);
@import "~element-ui/packages/theme-chalk/src/index";
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 全局加载动画
*/
@charset "utf-8";
@import "./spinner/dots.css";
@import "./spinner/gauge.css";
@import "./spinner/inner-circles.css";
@import "./spinner/plus.css";
$base-loading: ".vab-loading-type";
/* 自定义loading开始 */
#{$base-loading}1 {
display: flex;
width: 36px;
height: 36px;
margin: 0 auto 15px;
border: 3px solid transparent;
border-top-color: $base-color-blue;
border-bottom-color: $base-color-blue;
border-radius: 50%;
animation: vabLoading1-0 0.8s linear infinite;
}
#{$base-loading}1::before {
display: block;
width: 8px;
height: 8px;
margin: auto;
content: "";
border: 3px solid $base-color-blue;
border-radius: 50%;
animation: vabLoading1 0.5s alternate ease-in infinite;
}
@keyframes vabLoading1-0 {
to {
transform: rotate(360deg);
}
}
@keyframes vabLoading1 {
from {
transform: scale(0.5);
}
to {
transform: scale(1.2);
}
}
#{$base-loading}2 {
width: 20px;
height: 20px;
margin-top: -40px;
margin-left: -10px;
animation: vabLoading2 1s linear reverse infinite;
}
#{$base-loading}2::before {
display: block;
width: 36px;
height: 36px;
margin-top: -17px;
margin-left: -18px;
content: "";
animation: vabLoading2 0.4s linear infinite;
}
#{$base-loading}2::after {
display: block;
width: 8px;
height: 8px;
margin-top: -3px;
margin-left: -4px;
content: "";
animation: vabLoading2 0.4s linear infinite;
}
#{$base-loading}2::before,
#{$base-loading}2,
#{$base-loading}2::after {
position: absolute;
top: 40%;
left: 50%;
border: 3px solid transparent;
border-top-color: $base-color-blue;
border-right-color: $base-color-blue;
border-radius: 50%;
}
@keyframes vabLoading2 {
to {
transform: rotate(360deg);
}
}
#{$base-loading}3 {
display: inline-block;
width: 2.5em;
height: 3em;
margin-bottom: 15px;
border: 3px solid transparent;
border-top-color: $base-color-blue;
border-bottom-color: $base-color-blue;
border-radius: 50%;
animation: vabLoading3 2s ease infinite;
}
@keyframes vabLoading3 {
50% {
border-width: 8px;
transform: rotate(360deg) scale(0.4, 0.33);
}
100% {
border-width: 3px;
transform: rotate(720deg) scale(1, 1);
}
}
#{$base-loading}4 {
display: inline-block;
width: 30px;
height: 30px;
margin: 0 auto 10px;
border: 8px solid transparent;
border-bottom-color: $base-color-blue;
border-left-color: $base-color-blue;
border-radius: 50%;
animation: vabLoading4 1s linear infinite normal;
}
#{$base-loading}4::after {
display: block;
width: 15px;
height: 15px;
margin: 0;
content: " ";
border: 6px solid $base-color-blue;
border-bottom-color: transparent;
border-left-color: transparent;
border-radius: 50%;
}
@keyframes vabLoading4 {
0% {
opacity: 0.2;
transform: rotate(0deg);
}
50% {
opacity: 1;
transform: rotate(180deg);
}
100% {
opacity: 0.2;
transform: rotate(360deg);
}
}
#{$base-loading}5 {
display: block;
width: 0;
height: 0;
margin: 0 auto 15px;
border: solid 1.5em $base-color-blue;
border-right: solid 1.5em transparent;
border-left: solid 1.5em transparent;
border-radius: 100%;
animation: vabLoading5 1s linear infinite;
}
@keyframes vabLoading5 {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(60deg);
}
100% {
transform: rotate(360deg);
}
}
#{$base-loading}6 {
display: block;
width: 0;
height: 0;
margin: 0 auto 25px auto;
perspective: 200px;
}
#{$base-loading}6::before,
#{$base-loading}6::after {
position: absolute;
width: 20px;
height: 20px;
content: "";
background: rgba(0, 0, 0, 0);
animation: vabLoading6 0.5s infinite alternate;
}
#{$base-loading}6::before {
left: 0;
}
#{$base-loading}6::after {
right: 0;
animation-delay: 0.15s;
}
@keyframes vabLoading6 {
0% {
box-shadow: 0 0 0 rgba(0, 0, 0, 0);
transform: scale(1) translateY(0) rotateX(0deg);
}
100% {
background: $base-color-blue;
box-shadow: 0 25px 40px rgba($base-color-blue, 0.5);
transform: scale(1.2) translateY(-25px) rotateX(45deg);
}
}
#{$base-loading}7 {
display: block;
width: 25px;
height: 25px;
margin: 0 auto 15px auto;
border: 2px solid $base-color-blue;
border-top-color: rgba($base-color-blue, 0.2);
border-right-color: rgba($base-color-blue, 0.2);
border-bottom-color: rgba($base-color-blue, 0.2);
border-radius: 100%;
animation: vabLoading7 infinite 0.75s linear;
}
@keyframes vabLoading7 {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
#{$base-loading}8 {
position: relative;
box-sizing: border-box;
display: block;
width: 20px;
height: 20px;
margin: 0 auto 15px auto;
background-color: $base-color-blue;
border-radius: 50%;
box-shadow: 30px 0 0 0 $base-color-blue;
transform: translateX(-15px);
}
#{$base-loading}8::after {
position: absolute;
top: 8px;
left: 9px;
width: 10px;
height: 10px;
content: "";
background-color: $base-color-white;
border-radius: 50%;
box-shadow: 30px 0 0 0 $base-color-white;
animation: vabLoading8 2s ease-in-out infinite alternate;
}
@keyframes vabLoading8 {
0% {
left: 9px;
}
100% {
left: 1px;
}
}
#{$base-loading}9 {
position: relative;
box-sizing: border-box;
display: block;
width: 20px;
height: 20px;
margin: 0 auto 15px auto;
border: 1px $base-color-blue solid;
animation: vabLoading9 5s linear infinite;
}
#{$base-loading}9::after {
position: absolute;
top: -8px;
left: 0;
width: 4px;
height: 4px;
content: "";
background-color: $base-color-blue;
animation: vabLoading9_check 1s ease-in-out infinite;
}
@keyframes vabLoading9_check {
25% {
top: -8px;
left: 22px;
}
50% {
top: 22px;
left: 22px;
}
75% {
top: 22px;
left: -9px;
}
100% {
top: -7px;
left: -9px;
}
}
@keyframes vabLoading9 {
0% {
box-shadow: inset 0 0 0 0 rgba($base-color-blue, 0.5);
opacity: 0.5;
}
100% {
box-shadow: inset 0 -20px 0 0 $base-color-blue;
}
}
/* 自定义loading结束 */
@charset "utf-8";
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
margin: 0.67em 0;
font-size: 2em;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
border-bottom: none; /* 1 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
margin: 0; /* 2 */
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input {
/* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select {
/* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
padding: 0;
border-style: none;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
color: inherit; /* 2 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}
.dots-loader:not(:required) {
position: relative;
display: inline-block;
width: 7px;
height: 7px;
margin-bottom: 30px;
overflow: hidden;
text-indent: -9999px;
background: transparent;
border-radius: 100%;
box-shadow: #f86 -14px -14px 0 7px,
#fc6 14px -14px 0 7px,
#6d7 14px 14px 0 7px,
#4ae -14px 14px 0 7px;
transform-origin: 50% 50%;
animation: dots-loader 5s infinite ease-in-out;
}
@keyframes dots-loader {
0% {
box-shadow: #f86 -14px -14px 0 7px,
#fc6 14px -14px 0 7px,
#6d7 14px 14px 0 7px,
#4ae -14px 14px 0 7px;
}
8.33% {
box-shadow: #f86 14px -14px 0 7px,
#fc6 14px -14px 0 7px,
#6d7 14px 14px 0 7px,
#4ae -14px 14px 0 7px;
}
16.67% {
box-shadow: #f86 14px 14px 0 7px,
#fc6 14px 14px 0 7px,
#6d7 14px 14px 0 7px,
#4ae -14px 14px 0 7px;
}
25% {
box-shadow: #f86 -14px 14px 0 7px,
#fc6 -14px 14px 0 7px,
#6d7 -14px 14px 0 7px,
#4ae -14px 14px 0 7px;
}
33.33% {
box-shadow: #f86 -14px -14px 0 7px,
#fc6 -14px 14px 0 7px,
#6d7 -14px -14px 0 7px,
#4ae -14px -14px 0 7px;
}
41.67% {
box-shadow: #f86 14px -14px 0 7px,
#fc6 -14px 14px 0 7px,
#6d7 -14px -14px 0 7px,
#4ae 14px -14px 0 7px;
}
50% {
box-shadow: #f86 14px 14px 0 7px,
#fc6 -14px 14px 0 7px,
#6d7 -14px -14px 0 7px,
#4ae 14px -14px 0 7px;
}
58.33% {
box-shadow: #f86 -14px 14px 0 7px,
#fc6 -14px 14px 0 7px,
#6d7 -14px -14px 0 7px,
#4ae 14px -14px 0 7px;
}
66.67% {
box-shadow: #f86 -14px -14px 0 7px,
#fc6 -14px -14px 0 7px,
#6d7 -14px -14px 0 7px,
#4ae 14px -14px 0 7px;
}
75% {
box-shadow: #f86 14px -14px 0 7px,
#fc6 14px -14px 0 7px,
#6d7 14px -14px 0 7px,
#4ae 14px -14px 0 7px;
}
83.33% {
box-shadow: #f86 14px 14px 0 7px,
#fc6 14px -14px 0 7px,
#6d7 14px 14px 0 7px,
#4ae 14px 14px 0 7px;
}
91.67% {
box-shadow: #f86 -14px 14px 0 7px,
#fc6 14px -14px 0 7px,
#6d7 14px 14px 0 7px,
#4ae -14px 14px 0 7px;
}
100% {
box-shadow: #f86 -14px -14px 0 7px,
#fc6 14px -14px 0 7px,
#6d7 14px 14px 0 7px,
#4ae -14px 14px 0 7px;
}
}
.gauge-loader:not(:required) {
position: relative;
display: inline-block;
width: 64px;
height: 32px;
margin-bottom: 10px;
overflow: hidden;
text-indent: -9999px;
background: #6ca;
border-top-left-radius: 32px;
border-top-right-radius: 32px;
}
.gauge-loader:not(:required)::before {
position: absolute;
top: 5px;
left: 30px;
width: 4px;
height: 27px;
content: "";
background: white;
border-radius: 2px;
transform-origin: 50% 100%;
animation: gauge-loader 4000ms infinite ease;
}
.gauge-loader:not(:required)::after {
position: absolute;
top: 26px;
left: 26px;
width: 13px;
height: 13px;
content: "";
background: white;
-moz-border-radius: 8px;
-webkit-border-radius: 8px;
border-radius: 8px;
}
@keyframes gauge-loader {
0% {
transform: rotate(-50deg);
}
10% {
transform: rotate(20deg);
}
20% {
transform: rotate(60deg);
}
24% {
transform: rotate(60deg);
}
40% {
transform: rotate(-20deg);
}
54% {
transform: rotate(70deg);
}
56% {
transform: rotate(78deg);
}
58% {
transform: rotate(73deg);
}
60% {
transform: rotate(75deg);
}
62% {
transform: rotate(70deg);
}
70% {
transform: rotate(-20deg);
}
80% {
transform: rotate(20deg);
}
83% {
transform: rotate(25deg);
}
86% {
transform: rotate(20deg);
}
89% {
transform: rotate(25deg);
}
100% {
transform: rotate(-50deg);
}
}
.inner-circles-loader:not(:required) {
position: relative;
display: inline-block;
width: 50px;
height: 50px;
margin-bottom: 10px;
overflow: hidden;
text-indent: -9999px;
background: rgba(25, 165, 152, 0.5);
border-radius: 50%;
transform: translate3d(0, 0, 0);
}
.inner-circles-loader:not(:required)::before,
.inner-circles-loader:not(:required)::after {
position: absolute;
top: 0;
display: inline-block;
width: 50px;
height: 50px;
content: "";
border-radius: 50%;
}
.inner-circles-loader:not(:required)::before {
left: 0;
background: #c7efcf;
transform-origin: 0 50%;
animation: inner-circles-loader 3s infinite;
}
.inner-circles-loader:not(:required)::after {
right: 0;
background: #eef5db;
transform-origin: 100% 50%;
animation: inner-circles-loader 3s 0.2s reverse infinite;
}
@keyframes inner-circles-loader {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(360deg);
}
100% {
transform: rotate(0deg);
}
}
.plus-loader:not(:required) {
position: relative;
display: inline-block;
width: 48px;
height: 48px;
margin-bottom: 10px;
overflow: hidden;
text-indent: -9999px;
background: #f86;
-moz-border-radius: 24px;
-webkit-border-radius: 24px;
border-radius: 24px;
-moz-transform: rotateZ(90deg);
-ms-transform: rotateZ(90deg);
-webkit-transform: rotateZ(90deg);
transform: rotateZ(90deg);
-moz-transform-origin: 50% 50%;
-ms-transform-origin: 50% 50%;
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
-moz-animation: plus-loader-background 3s infinite ease-in-out;
-webkit-animation: plus-loader-background 3s infinite ease-in-out;
animation: plus-loader-background 3s infinite ease-in-out;
}
.plus-loader:not(:required)::after {
position: absolute;
top: 0;
right: 50%;
width: 50%;
height: 100%;
content: "";
background: #f86;
-moz-border-radius: 24px 0 0 24px;
-webkit-border-radius: 24px;
border-radius: 24px 0 0 24px;
-moz-transform-origin: 100% 50%;
-ms-transform-origin: 100% 50%;
-webkit-transform-origin: 100% 50%;
transform-origin: 100% 50%;
-moz-animation: plus-loader-top 3s infinite linear;
-webkit-animation: plus-loader-top 3s infinite linear;
animation: plus-loader-top 3s infinite linear;
}
.plus-loader:not(:required)::before {
position: absolute;
top: 0;
right: 50%;
width: 50%;
height: 100%;
content: "";
background: #fc6;
-moz-border-radius: 24px 0 0 24px;
-webkit-border-radius: 24px;
border-radius: 24px 0 0 24px;
-moz-transform-origin: 100% 50%;
-ms-transform-origin: 100% 50%;
-webkit-transform-origin: 100% 50%;
transform-origin: 100% 50%;
-moz-animation: plus-loader-bottom 3s infinite linear;
-webkit-animation: plus-loader-bottom 3s infinite linear;
animation: plus-loader-bottom 3s infinite linear;
}
@keyframes plus-loader-top {
2.5% {
background: #f86;
-moz-transform: rotateY(0deg);
-ms-transform: rotateY(0deg);
-webkit-transform: rotateY(0deg);
transform: rotateY(0deg);
-moz-animation-timing-function: ease-in;
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
13.75% {
background: #ff430d;
-moz-transform: rotateY(90deg);
-ms-transform: rotateY(90deg);
-webkit-transform: rotateY(90deg);
transform: rotateY(90deg);
-moz-animation-timing-function: step-start;
-webkit-animation-timing-function: step-start;
animation-timing-function: step-start;
}
13.76% {
background: #ffae0d;
-moz-transform: rotateY(90deg);
-ms-transform: rotateY(90deg);
-webkit-transform: rotateY(90deg);
transform: rotateY(90deg);
-moz-animation-timing-function: ease-out;
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
25% {
background: #fc6;
-moz-transform: rotateY(180deg);
-ms-transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
}
27.5% {
background: #fc6;
-moz-transform: rotateY(180deg);
-ms-transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
-moz-animation-timing-function: ease-in;
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
41.25% {
background: #ffae0d;
-moz-transform: rotateY(90deg);
-ms-transform: rotateY(90deg);
-webkit-transform: rotateY(90deg);
transform: rotateY(90deg);
-moz-animation-timing-function: step-start;
-webkit-animation-timing-function: step-start;
animation-timing-function: step-start;
}
41.26% {
background: #2cc642;
-moz-transform: rotateY(90deg);
-ms-transform: rotateY(90deg);
-webkit-transform: rotateY(90deg);
transform: rotateY(90deg);
-moz-animation-timing-function: ease-out;
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
50% {
background: #6d7;
-moz-transform: rotateY(0deg);
-ms-transform: rotateY(0deg);
-webkit-transform: rotateY(0deg);
transform: rotateY(0deg);
}
52.5% {
background: #6d7;
-moz-transform: rotateY(0deg);
-ms-transform: rotateY(0deg);
-webkit-transform: rotateY(0deg);
transform: rotateY(0deg);
-moz-animation-timing-function: ease-in;
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
63.75% {
background: #2cc642;
-moz-transform: rotateY(90deg);
-ms-transform: rotateY(90deg);
-webkit-transform: rotateY(90deg);
transform: rotateY(90deg);
-moz-animation-timing-function: step-start;
-webkit-animation-timing-function: step-start;
animation-timing-function: step-start;
}
63.76% {
background: #1386d2;
-moz-transform: rotateY(90deg);
-ms-transform: rotateY(90deg);
-webkit-transform: rotateY(90deg);
transform: rotateY(90deg);
-moz-animation-timing-function: ease-out;
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out;
}
75% {
background: #4ae;
-moz-transform: rotateY(180deg);
-ms-transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
}
77.5% {
background: #4ae;
-moz-transform: rotateY(180deg);
-ms-transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
-moz-animation-timing-function: ease-in;
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
91.25% {
background: #1386d2;
-moz-transform: rotateY(90deg);
-ms-transform: rotateY(90deg);
-webkit-transform: rotateY(90deg);
transform: rotateY(90deg);
-moz-animation-timing-function: step-start;
-webkit-animation-timing-function: step-start;
animation-timing-function: step-start;
}
91.26% {
background: #ff430d;
-moz-transform: rotateY(90deg);
-ms-transform: rotateY(90deg);
-webkit-transform: rotateY(90deg);
transform: rotateY(90deg);
-moz-animation-timing-function: ease-in;
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
}
100% {
background: #f86;
-moz-transform: rotateY(0deg);
-ms-transform: rotateY(0deg);
-webkit-transform: rotateY(0deg);
transform: rotateY(0deg);
-moz-animation-timing-function: step-start;
-webkit-animation-timing-function: step-start;
animation-timing-function: step-start;
}
}
@keyframes plus-loader-bottom {
0% {
background: #fc6;
-moz-animation-timing-function: step-start;
-webkit-animation-timing-function: step-start;
animation-timing-function: step-start;
}
50% {
background: #fc6;
-moz-animation-timing-function: step-start;
-webkit-animation-timing-function: step-start;
animation-timing-function: step-start;
}
75% {
background: #4ae;
-moz-animation-timing-function: step-start;
-webkit-animation-timing-function: step-start;
animation-timing-function: step-start;
}
100% {
background: #4ae;
-moz-animation-timing-function: step-start;
-webkit-animation-timing-function: step-start;
animation-timing-function: step-start;
}
}
@keyframes plus-loader-background {
0% {
background: #f86;
-moz-transform: rotateZ(180deg);
-ms-transform: rotateZ(180deg);
-webkit-transform: rotateZ(180deg);
transform: rotateZ(180deg);
}
25% {
background: #f86;
-moz-transform: rotateZ(180deg);
-ms-transform: rotateZ(180deg);
-webkit-transform: rotateZ(180deg);
transform: rotateZ(180deg);
-moz-animation-timing-function: step-start;
-webkit-animation-timing-function: step-start;
animation-timing-function: step-start;
}
27.5% {
background: #6d7;
-moz-transform: rotateZ(90deg);
-ms-transform: rotateZ(90deg);
-webkit-transform: rotateZ(90deg);
transform: rotateZ(90deg);
}
50% {
background: #6d7;
-moz-transform: rotateZ(90deg);
-ms-transform: rotateZ(90deg);
-webkit-transform: rotateZ(90deg);
transform: rotateZ(90deg);
-moz-animation-timing-function: step-start;
-webkit-animation-timing-function: step-start;
animation-timing-function: step-start;
}
52.5% {
background: #6d7;
-moz-transform: rotateZ(0deg);
-ms-transform: rotateZ(0deg);
-webkit-transform: rotateZ(0deg);
transform: rotateZ(0deg);
}
75% {
background: #6d7;
-moz-transform: rotateZ(0deg);
-ms-transform: rotateZ(0deg);
-webkit-transform: rotateZ(0deg);
transform: rotateZ(0deg);
-moz-animation-timing-function: step-start;
-webkit-animation-timing-function: step-start;
animation-timing-function: step-start;
}
77.5% {
background: #f86;
-moz-transform: rotateZ(270deg);
-ms-transform: rotateZ(270deg);
-webkit-transform: rotateZ(270deg);
transform: rotateZ(270deg);
}
100% {
background: #f86;
-moz-transform: rotateZ(270deg);
-ms-transform: rotateZ(270deg);
-webkit-transform: rotateZ(270deg);
transform: rotateZ(270deg);
-moz-animation-timing-function: step-start;
-webkit-animation-timing-function: step-start;
animation-timing-function: step-start;
}
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 暗黑之子主题(VIP群专享)
*/
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 荣耀典藏主题(VIP群专享)
*/
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 绿荫操场主题(VIP群专享)
*/
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 海洋之心主题(VIP群专享)
*/
/**
* @copyright chuzhixin 1204505056@qq.com
* @description vue过渡动画
*/
@charset "utf-8";
.fade-transform-leave-active,
.fade-transform-enter-active {
transition: $base-transition;
}
.fade-transform-enter {
opacity: 0;
transform: translateX(-30px);
}
.fade-transform-leave-to {
opacity: 0;
transform: translateX(30px);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 全局样式
*/
@charset "utf-8";
@import "./normalize.scss";
@import "./transition.scss";
@import "./loading.scss";
@import "./themes/ocean.scss";
@import "./themes/green.scss";
@import "./themes/glory.scss";
@import "./themes/dark.scss";
$base: ".vab";
@mixin scrollbar {
max-height: 88vh;
margin-bottom: 0.5vh;
overflow-y: auto;
&::-webkit-scrollbar {
width: 0;
height: 0;
background: transparent;
}
&::-webkit-scrollbar-thumb {
background-color: rgba(144, 147, 153, 0.3);
border-radius: 10px;
}
&::-webkit-scrollbar-thumb:hover {
background-color: rgba(144, 147, 153, 0.3);
}
}
@mixin base-scrollbar {
&::-webkit-scrollbar {
width: 13px;
height: 13px;
}
&::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.4);
background-clip: padding-box;
border: 3px solid transparent;
border-radius: 7px;
}
&::-webkit-scrollbar-thumb:hover {
background-color: rgba(0, 0, 0, 0.5);
}
&::-webkit-scrollbar-track {
background-color: transparent;
}
&::-webkit-scrollbar-track:hover {
background-color: #f8fafc;
}
}
img {
object-fit: cover;
}
a {
color: $base-color-blue;
text-decoration: none;
cursor: pointer;
}
html {
body {
position: relative;
height: 100vh;
padding: 0;
margin: 0;
font-family: Avenir, Helvetica, Arial, sans-serif;
font-size: $base-font-size-default;
color: #2c3e50;
background: #f6f8f9;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@include base-scrollbar;
div {
@include base-scrollbar;
}
svg,
i {
&:hover {
opacity: 0.8;
}
}
/* el-tag开始 */
.el-tag + .el-tag {
margin-left: 10px;
}
/* el-tag结束 */
/* markdown编辑器开始 */
.editor-toolbar {
.no-mobile,
.fa-question-circle {
display: none;
}
}
/* markdown编辑器结束 */
/* 间隔线开始 */
.el-divider--horizontal {
margin: 10px 0 25px 0;
.el-divider__text {
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
}
/* 间隔线结束 */
/* 大图展示开始 */
.el-image-viewer {
&__close {
.el-icon-circle-close {
color: $base-color-white;
}
}
}
/* 大图展示结束 */
.vue-admin-beautiful-wrapper {
.app-main-container {
@include base-scrollbar;
> [class*="-container"] {
padding: $base-padding;
background: $base-color-white;
}
}
}
/* 进度条开始 */
#nprogress {
position: fixed;
z-index: $base-z-index;
.bar {
background: $base-color-blue !important;
}
.peg {
box-shadow: 0 0 10px $base-color-blue, 0 0 5px $base-color-blue !important;
}
}
/* 进度条结束 */
/* 表格开始 */
.el-table {
.el-table__body-wrapper {
@include base-scrollbar;
}
th {
background: #f5f7fa;
}
td,
th {
position: relative;
box-sizing: border-box;
padding: 7.5px 0;
.cell {
font-size: $base-font-size-default;
font-weight: normal;
color: #606266;
.el-image {
width: 50px;
height: 50px;
border-radius: $base-border-radius;
}
}
}
}
/* 表格结束 */
/* 分页开始 */
.el-pagination {
padding: 2px 5px;
margin: 15px 0 0 0;
font-weight: normal;
color: $base-color-black;
text-align: center;
}
/* 分页结束 */
/* 菜单开始 */
.el-menu.el-menu--popup.el-menu--popup-right-start {
@include scrollbar;
}
.el-menu.el-menu--popup.el-menu--popup-bottom-start {
@include scrollbar;
}
.el-submenu__title i {
color: $base-color-white;
}
/* 菜单结束 */
/* 弹窗开始 */
.el-dialog,
.el-message-box {
&__body {
border-top: 1px solid $base-border-color;
.el-form {
padding-right: 30px;
}
}
&__footer {
padding: $base-padding;
text-align: right;
border-top: 1px solid $base-border-color;
}
&__content {
padding: 20px 20px 20px 20px;
}
}
/* 弹窗结束 */
/* 卡片开始 */
.el-card {
margin-bottom: 15px;
&__body {
padding: $base-padding;
}
}
/* 卡片结束 */
/* 下拉树样式-----------开始 */
.select-tree-popper {
.el-scrollbar {
.el-scrollbar__view {
.el-select-dropdown__item {
height: auto;
max-height: 274px;
padding: 0;
overflow-y: auto;
line-height: 26px;
}
}
}
}
/* 下拉树样式-----------结束 */
}
}
/**
* @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: 256px;
//纵向布局时左侧导航未折叠时右侧内容的宽度
$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;
}
import { storage, tokenTableName } from "@/config/settings";
import cookie from "js-cookie";
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 获取accessToken
* @returns {string|ActiveX.IXMLDOMNode|Promise<any>|any|IDBRequest<any>|MediaKeyStatus|FormDataEntryValue|Function|Promise<Credential | null>}
*/
export function getAccessToken() {
if (storage) {
if ("localStorage" === storage) {
return localStorage.getItem(tokenTableName);
} else if ("sessionStorage" === storage) {
return sessionStorage.getItem(tokenTableName);
} else if ("cookie" === storage) {
return cookie.get(tokenTableName);
} else {
return localStorage.getItem(tokenTableName);
}
} else {
return localStorage.getItem(tokenTableName);
}
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 存储accessToken
* @param accessToken
* @returns {void|*}
*/
export function setAccessToken(accessToken) {
if (storage) {
if ("localStorage" === storage) {
return localStorage.setItem(tokenTableName, accessToken);
} else if ("sessionStorage" === storage) {
return sessionStorage.setItem(tokenTableName, accessToken);
} else if ("cookie" === storage) {
return cookie.set(tokenTableName, accessToken);
} else {
return localStorage.setItem(tokenTableName, accessToken);
}
} else {
return localStorage.setItem(tokenTableName, accessToken);
}
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 移除accessToken
* @returns {void|Promise<void>}
*/
export function removeAccessToken() {
if (storage) {
if ("localStorage" === storage) {
return localStorage.removeItem(tokenTableName);
} else if ("sessionStorage" === storage) {
return sessionStorage.clear();
} else if ("cookie" === storage) {
return cookie.remove(tokenTableName);
} else {
return localStorage.removeItem(tokenTableName);
}
} else {
return localStorage.removeItem(tokenTableName);
}
}
import Vue from "vue";
import Clipboard from "clipboard";
function clipboardSuccess() {
Vue.prototype.$baseMessage("复制成功", "success");
}
function clipboardError() {
Vue.prototype.$baseMessage("复制失败", "error");
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 复制数据
* @param text
* @param event
*/
export default function handleClipboard(text, event) {
const clipboard = new Clipboard(event.target, {
text: () => text,
});
clipboard.on("success", () => {
clipboardSuccess();
clipboard.destroy();
});
clipboard.on("error", () => {
clipboardError();
clipboard.destroy();
});
clipboard.onClick(event);
}
import { JSEncrypt } from "jsencrypt";
import { getPublicKey } from "@/api/publicKey";
const privateKey =
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMFPa+v52FkSUXvcUnrGI/XzW3EpZRI0s9BCWJ3oNQmEYA5luWW5p8h0uadTIoTyYweFPdH4hveyxlwmS7oefvbIdiP+o+QIYW/R4Wjsb4Yl8MhR4PJqUE3RCy6IT9fM8ckG4kN9ECs6Ja8fQFc6/mSl5dJczzJO3k1rWMBhKJD/AgMBAAECgYEAucMakH9dWeryhrYoRHcXo4giPVJsH9ypVt4KzmOQY/7jV7KFQK3x//27UoHfUCak51sxFw9ek7UmTPM4HjikA9LkYeE7S381b4QRvFuf3L6IbMP3ywJnJ8pPr2l5SqQ00W+oKv+w/VmEsyUHr+k4Z+4ik+FheTkVWp566WbqFsECQQDjYaMcaKw3j2Zecl8T6eUe7fdaRMIzp/gcpPMfT/9rDzIQk+7ORvm1NI9AUmFv/FAlfpuAMrdL2n7p9uznWb7RAkEA2aP934kbXg5bdV0R313MrL+7WTK/qdcYxATUbMsMuWWQBoS5irrt80WCZbG48hpocJavLNjbtrjmUX3CuJBmzwJAOJg8uP10n/+ZQzjEYXh+BszEHDuw+pp8LuT/fnOy5zrJA0dO0RjpXijO3vuiNPVgHXT9z1LQPJkNrb5ACPVVgQJBALPeb4uV0bNrJDUb5RB4ghZnIxv18CcaqNIft7vuGCcFBAIPIRTBprR+RuVq+xHDt3sNXdsvom4h49+Hky1b0ksCQBBwUtVaqH6ztCtwUF1j2c/Zcrt5P/uN7IHAd44K0gIJc1+Csr3qPG+G2yoqRM8KVqLI8Z2ZYn9c+AvEE+L9OQY=";
/**
* @copyright chuzhixin 1204505056@qq.com
* @description RSA加密
* @param data
* @returns {Promise<{param: PromiseLike<ArrayBuffer>}|*>}
*/
export async function encryptedData(data) {
let publicKey = "";
const res = await getPublicKey();
publicKey = res.data.publicKey;
if (res.data.mockServer) {
publicKey = "";
}
if (publicKey == "") {
return data;
}
const encrypt = new JSEncrypt();
encrypt.setPublicKey(
`-----BEGIN PUBLIC KEY-----${publicKey}-----END PUBLIC KEY-----`
);
data = encrypt.encrypt(JSON.stringify(data));
return {
param: data,
};
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description RSA解密
* @param data
* @returns {PromiseLike<ArrayBuffer>}
*/
export function decryptedData(data) {
const decrypt = new JSEncrypt();
decrypt.setPrivateKey(
`-----BEGIN RSA PRIVATE KEY-----${privateKey}-----END RSA PRIVATE KEY-----`
);
data = decrypt.decrypt(JSON.stringify(data));
return data;
}
import Vue from "vue";
import store from "@/store";
import { isArray, isString } from "@/utils/validate";
import { errorLog } from "@/config/settings";
const needErrorLog = errorLog;
const checkNeed = () => {
const env = process.env.NODE_ENV;
if (isString(needErrorLog)) {
return env === needErrorLog;
}
if (isArray(needErrorLog)) {
return needErrorLog.includes(env);
}
return false;
};
if (checkNeed()) {
Vue.config.errorHandler = (err, vm, info) => {
console.error("vue-admin-beautiful错误拦截:", err, vm, info);
const url = window.location.href;
Vue.nextTick(() => {
store.dispatch("errorLog/addErrorLog", { err, vm, info, url });
});
};
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description all模式渲染后端返回路由
* @param constantRoutes
* @returns {*}
*/
export function filterAllRoutes(constantRoutes) {
return constantRoutes.filter((route) => {
if (route.component) {
if (route.component === "Layout") {
route.component = (resolve) => require(["@/layouts"], resolve);
} else if (route.component === "EmptyLayout") {
route.component = (resolve) =>
require(["@/layouts/EmptyLayout"], resolve);
} else {
let path = "views/" + route.component;
if (
new RegExp("^/views/.*$").test(route.component) ||
new RegExp("^views/.*$").test(route.component)
) {
path = route.component;
} else if (new RegExp("^/.*$").test(route.component)) {
path = "views" + route.component;
} else if (new RegExp("^@views/.*$").test(route.component)) {
path = route.component.slice(1);
} else {
path = "views/" + route.component;
}
route.component = (resolve) => require([`@/${path}`], resolve);
}
}
if (route.children && route.children.length) {
route.children = filterAllRoutes(route.children);
}
if (route.children && route.children.length === 0) {
delete route.children;
}
return true;
});
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断当前路由是否包含权限
* @param permissions
* @param route
* @returns {boolean|*}
*/
function hasPermission(permissions, route) {
if (route.meta && route.meta.permissions) {
return permissions.some((role) => route.meta.permissions.includes(role));
} else {
return true;
}
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description intelligence模式根据permissions数组拦截路由
* @param routes
* @param permissions
* @returns {[]}
*/
export function filterAsyncRoutes(routes, permissions) {
const finallyRoutes = [];
routes.forEach((route) => {
const item = { ...route };
if (hasPermission(permissions, item)) {
if (item.children) {
item.children = filterAsyncRoutes(item.children, permissions);
}
finallyRoutes.push(item);
}
});
return finallyRoutes;
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 格式化时间
* @param time
* @param cFormat
* @returns {string|null}
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0) {
return null;
}
const format = cFormat || "{y}-{m}-{d} {h}:{i}:{s}";
let date;
if (typeof time === "object") {
date = time;
} else {
if (typeof time === "string" && /^[0-9]+$/.test(time)) {
time = parseInt(time);
}
if (typeof time === "number" && time.toString().length === 10) {
time = time * 1000;
}
date = new Date(time);
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay(),
};
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key];
if (key === "a") {
return ["日", "一", "二", "三", "四", "五", "六"][value];
}
if (result.length > 0 && value < 10) {
value = "0" + value;
}
return value || 0;
});
return time_str;
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 格式化时间
* @param time
* @param option
* @returns {string}
*/
export function formatTime(time, option) {
if (("" + time).length === 10) {
time = parseInt(time) * 1000;
} else {
time = +time;
}
const d = new Date(time);
const now = Date.now();
const diff = (now - d) / 1000;
if (diff < 30) {
return "刚刚";
} else if (diff < 3600) {
// less 1 hour
return Math.ceil(diff / 60) + "分钟前";
} else if (diff < 3600 * 24) {
return Math.ceil(diff / 3600) + "小时前";
} else if (diff < 3600 * 24 * 2) {
return "1天前";
}
if (option) {
return parseTime(time, option);
} else {
return (
d.getMonth() +
1 +
"月" +
d.getDate() +
"日" +
d.getHours() +
"时" +
d.getMinutes() +
"分"
);
}
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 将url请求参数转为json格式
* @param url
* @returns {{}|any}
*/
export function paramObj(url) {
const search = url.split("?")[1];
if (!search) {
return {};
}
return JSON.parse(
'{"' +
decodeURIComponent(search)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"')
.replace(/\+/g, " ") +
'"}'
);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 父子关系的数组转换成树形结构数据
* @param data
* @returns {*}
*/
export function translateDataToTree(data) {
const parent = data.filter(
(value) => value.parentId === "undefined" || value.parentId == null
);
const children = data.filter(
(value) => value.parentId !== "undefined" && value.parentId != null
);
const translator = (parent, children) => {
parent.forEach((parent) => {
children.forEach((current, index) => {
if (current.parentId === parent.id) {
const temp = JSON.parse(JSON.stringify(children));
temp.splice(index, 1);
translator([current], temp);
typeof parent.children !== "undefined"
? parent.children.push(current)
: (parent.children = [current]);
}
});
});
};
translator(parent, children);
return parent;
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 树形结构数据转换成父子关系的数组
* @param data
* @returns {[]}
*/
export function translateTreeToData(data) {
const result = [];
data.forEach((item) => {
const loop = (data) => {
result.push({
id: data.id,
name: data.name,
parentId: data.parentId,
});
const child = data.children;
if (child) {
for (let i = 0; i < child.length; i++) {
loop(child[i]);
}
}
};
loop(item);
});
return result;
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 10位时间戳转换
* @param time
* @returns {string}
*/
export function tenBitTimestamp(time) {
const date = new Date(time * 1000);
const y = date.getFullYear();
let m = date.getMonth() + 1;
m = m < 10 ? "" + m : m;
let d = date.getDate();
d = d < 10 ? "" + d : d;
let h = date.getHours();
h = h < 10 ? "0" + h : h;
let minute = date.getMinutes();
let second = date.getSeconds();
minute = minute < 10 ? "0" + minute : minute;
second = second < 10 ? "0" + second : second;
return y + "年" + m + "月" + d + "日 " + h + ":" + minute + ":" + second; //组合
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 13位时间戳转换
* @param time
* @returns {string}
*/
export function thirteenBitTimestamp(time) {
const date = new Date(time / 1);
const y = date.getFullYear();
let m = date.getMonth() + 1;
m = m < 10 ? "" + m : m;
let d = date.getDate();
d = d < 10 ? "" + d : d;
let h = date.getHours();
h = h < 10 ? "0" + h : h;
let minute = date.getMinutes();
let second = date.getSeconds();
minute = minute < 10 ? "0" + minute : minute;
second = second < 10 ? "0" + second : second;
return y + "年" + m + "月" + d + "日 " + h + ":" + minute + ":" + second; //组合
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 获取随机id
* @param length
* @returns {string}
*/
export function uuid(length = 32) {
const num = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
let str = "";
for (let i = 0; i < length; i++) {
str += num.charAt(Math.floor(Math.random() * num.length));
}
return str;
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description m到n的随机数
* @param m
* @param n
* @returns {number}
*/
export function random(m, n) {
return Math.floor(Math.random() * (m - n) + n);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description addEventListener
* @type {function(...[*]=)}
*/
export const on = (function () {
return function (element, event, handler, useCapture = false) {
if (element && event && handler) {
element.addEventListener(event, handler, useCapture);
}
};
})();
/**
* @copyright chuzhixin 1204505056@qq.com
* @description removeEventListener
* @type {function(...[*]=)}
*/
export const off = (function () {
return function (element, event, handler, useCapture = false) {
if (element && event) {
element.removeEventListener(event, handler, useCapture);
}
};
})();
import { title } from "@/config/settings";
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 设置标题
* @param pageTitle
* @returns {string}
*/
export default function getPageTitle(pageTitle) {
if (pageTitle) {
return `${pageTitle}-${title}`;
}
return `${title}`;
}
import store from "@/store";
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 检查权限
* @param value
* @returns {boolean}
*/
export default function checkPermission(value) {
if (value && value instanceof Array && value.length > 0) {
const permissions = store.getters["user/permissions"];
const permissionPermissions = value;
return permissions.some((role) => {
return permissionPermissions.includes(role);
});
} else {
return false;
}
}
import Vue from "vue";
import axios from "axios";
import {
baseURL,
contentType,
debounce,
invalidCode,
noPermissionCode,
requestTimeout,
successCode,
tokenName,
loginInterception,
} from "@/config/settings";
import store from "@/store";
import qs from "qs";
import router from "@/router";
import { isArray } from "@/utils/validate";
let loadingInstance;
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断当前url是否需要加loading
* @param {*} config
* @returns
*/
const needLoading = (config) => {
let status = false;
debounce.forEach((item) => {
if (Vue.prototype.$baseLodash.includes(config.url, item)) {
status = true;
}
});
return status;
};
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 处理code异常
* @param {*} code
* @param {*} msg
*/
const handleCode = (code, msg) => {
switch (code) {
case invalidCode:
Vue.prototype.$baseMessage(msg || `后端接口${code}异常`, "error");
store.dispatch("user/resetAccessToken").catch(() => {});
if (loginInterception) {
location.reload();
}
break;
case noPermissionCode:
router.push({ path: "/401" }).catch(() => {});
break;
default:
Vue.prototype.$baseMessage(msg || `后端接口${code}异常`, "error");
break;
}
};
const instance = axios.create({
baseURL,
timeout: requestTimeout,
headers: {
"Content-Type": contentType,
},
});
instance.interceptors.request.use(
(config) => {
if (store.getters["user/accessToken"]) {
config.headers[tokenName] = store.getters["user/accessToken"];
}
//这里会过滤所有为空、0、false的key,如果不需要请自行注释
if (config.data)
config.data = Vue.prototype.$baseLodash.pickBy(
config.data,
Vue.prototype.$baseLodash.identity
);
if (
contentType === "application/x-www-form-urlencoded;charset=UTF-8" &&
config.data
) {
config.data = qs.stringify(config.data);
}
if (needLoading(config)) {
loadingInstance = Vue.prototype.$baseLoading();
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
instance.interceptors.response.use(
(response) => {
if (loadingInstance) loadingInstance.close();
const { status, data, config } = response;
const { code, msg } = data;
// 操作正常Code数组
const codeVerificationArray = isArray(successCode)
? [...successCode]
: [...[successCode]];
// 是否操作正常
if (codeVerificationArray.includes(code)) {
return data;
} else {
handleCode(code, msg);
return Promise.reject(
"vue-admin-beautiful请求异常拦截:" +
JSON.stringify({ url: config.url, code, msg }) || "Error"
);
}
},
(error) => {
if (loadingInstance) loadingInstance.close();
const { response, message } = error;
if (error.response && error.response.data) {
const { status, data } = response;
handleCode(status, data.msg || message);
return Promise.reject(error);
} else {
let { message } = error;
if (message === "Network Error") {
message = "后端接口连接异常";
}
if (message.includes("timeout")) {
message = "后端接口请求超时";
}
if (message.includes("Request failed with status code")) {
const code = message.substr(message.length - 3);
message = "后端接口" + code + "异常";
}
Vue.prototype.$baseMessage(message || `后端接口未知异常`, "error");
return Promise.reject(error);
}
}
);
export default instance;
import { loadingText, messageDuration, title } from "@/config/settings";
import * as lodash from "lodash";
import { Loading, Message, MessageBox, Notification } from "element-ui";
import store from "@/store";
import { getAccessToken } from "@/utils/accessToken";
const accessToken = store.getters["user/accessToken"];
const layout = store.getters["settings/layout"];
const install = (Vue, opts = {}) => {
/* 全局accessToken */
Vue.prototype.$baseAccessToken = () => {
return accessToken || getAccessToken();
};
/* 全局标题 */
Vue.prototype.$baseTitle = (() => {
return title;
})();
/* 全局加载层 */
Vue.prototype.$baseLoading = (index, text) => {
let loading;
if (!index) {
loading = Loading.service({
lock: true,
text: text || loadingText,
background: "hsla(0,0%,100%,.8)",
});
} else {
loading = Loading.service({
lock: true,
text: text || loadingText,
spinner: "vab-loading-type" + index,
background: "hsla(0,0%,100%,.8)",
});
}
return loading;
};
/* 全局多彩加载层 */
Vue.prototype.$baseColorfullLoading = (index, text) => {
let loading;
if (!index) {
loading = Loading.service({
lock: true,
text: text || loadingText,
spinner: "dots-loader",
background: "hsla(0,0%,100%,.8)",
});
} else {
switch (index) {
case 1:
index = "dots";
break;
case 2:
index = "gauge";
break;
case 3:
index = "inner-circles";
break;
case 4:
index = "plus";
break;
}
loading = Loading.service({
lock: true,
text: text || loadingText,
spinner: index + "-loader",
background: "hsla(0,0%,100%,.8)",
});
}
return loading;
};
/* 全局Message */
Vue.prototype.$baseMessage = (message, type) => {
Message({
offset: 60,
showClose: true,
message: message,
type: type,
dangerouslyUseHTMLString: true,
duration: messageDuration,
});
};
/* 全局Alert */
Vue.prototype.$baseAlert = (content, title, callback) => {
MessageBox.alert(content, title || "温馨提示", {
confirmButtonText: "确定",
dangerouslyUseHTMLString: true,
callback: (action) => {
if (callback) {
callback();
}
},
});
};
/* 全局Confirm */
Vue.prototype.$baseConfirm = (content, title, callback1, callback2) => {
MessageBox.confirm(content, title || "温馨提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
closeOnClickModal: false,
type: "warning",
})
.then(() => {
if (callback1) {
callback1();
}
})
.catch(() => {
if (callback2) {
callback2();
}
});
};
/* 全局Notification */
Vue.prototype.$baseNotify = (message, title, type, position) => {
Notification({
title: title,
message: message,
position: position || "top-right",
type: type || "success",
duration: messageDuration,
});
};
/* 全局TableHeight */
Vue.prototype.$baseTableHeight = (formType) => {
let height = window.innerHeight;
let paddingHeight = 400;
const formHeight = 50;
if (layout === "vertical") {
paddingHeight = 340;
}
if ("number" == typeof formType) {
height = height - paddingHeight - formHeight * formType;
} else {
height = height - paddingHeight;
}
return height;
};
/* 全局map图层 */
Vue.prototype.$baseMap = () => {
return new maptalks.Map("map", {
center: [116.41348403785, 39.910843952376],
zoom: 12,
minZoom: 1,
maxZoom: 19,
spatialReference: {
projection: "baidu",
},
attribution: {
content: "&copy; vue-admin-beautiful",
},
baseLayer: new maptalks.TileLayer("base", {
cssFilter: "sepia(100%) invert(90%)",
urlTemplate:
"http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&scaler=1&p=1",
subdomains: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
attribution:
'&copy; <a target="_blank" href="http://map.baidu.com">Baidu</a>',
}),
});
};
/* 全局lodash */
Vue.prototype.$baseLodash = lodash;
/* 全局事件总线 */
Vue.prototype.$baseEventBus = new Vue();
};
if (typeof window !== "undefined" && window.Vue) {
install(window.Vue);
}
export default install;
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判读是否为外链
* @param path
* @returns {boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 校验密码是否小于6位
* @param str
* @returns {boolean}
*/
export function isPassword(str) {
return str.length >= 6;
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否为数字
* @param value
* @returns {boolean}
*/
export function isNumber(value) {
const reg = /^[0-9]*$/;
return reg.test(value);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否是名称
* @param value
* @returns {boolean}
*/
export function isName(value) {
const reg = /^[\u4e00-\u9fa5a-zA-Z0-9]+$/;
return reg.test(value);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否为IP
* @param ip
* @returns {boolean}
*/
export function isIP(ip) {
const reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
return reg.test(ip);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否是传统网站
* @param url
* @returns {boolean}
*/
export function isUrl(url) {
const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;
return reg.test(url);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否是小写字母
* @param str
* @returns {boolean}
*/
export function isLowerCase(str) {
const reg = /^[a-z]+$/;
return reg.test(str);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否是大写字母
* @param str
* @returns {boolean}
*/
export function isUpperCase(str) {
const reg = /^[A-Z]+$/;
return reg.test(str);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否是大写字母开头
* @param str
* @returns {boolean}
*/
export function isAlphabets(str) {
const reg = /^[A-Za-z]+$/;
return reg.test(str);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否是字符串
* @param str
* @returns {boolean}
*/
export function isString(str) {
return typeof str === "string" || str instanceof String;
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否是数组
* @param arg
* @returns {arg is any[]|boolean}
*/
export function isArray(arg) {
if (typeof Array.isArray === "undefined") {
return Object.prototype.toString.call(arg) === "[object Array]";
}
return Array.isArray(arg);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否是端口号
* @param str
* @returns {boolean}
*/
export function isPort(str) {
const reg = /^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/;
return reg.test(str);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否是手机号
* @param str
* @returns {boolean}
*/
export function isPhone(str) {
const reg = /^1\d{10}$/;
return reg.test(str);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否是身份证号(第二代)
* @param str
* @returns {boolean}
*/
export function isIdCard(str) {
const reg = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
return reg.test(str);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否是邮箱
* @param str
* @returns {boolean}
*/
export function isEmail(str) {
const reg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
return reg.test(str);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否中文
* @param str
* @returns {boolean}
*/
export function isChina(str) {
const reg = /^[\u4E00-\u9FA5]{2,4}$/;
return reg.test(str);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否为空
* @param str
* @returns {boolean}
*/
export function isBlank(str) {
return (
str == null ||
false ||
str === "" ||
str.trim() === "" ||
str.toLocaleLowerCase().trim() === "null"
);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否为固话
* @param str
* @returns {boolean}
*/
export function isTel(str) {
const reg = /^(400|800)([0-9\\-]{7,10})|(([0-9]{4}|[0-9]{3})(-| )?)?([0-9]{7,8})((-| |转)*([0-9]{1,4}))?$/;
return reg.test(str);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断是否为数字且最多两位小数
* @param str
* @returns {boolean}
*/
export function isNum(str) {
const reg = /^\d+(\.\d{1,2})?$/;
return reg.test(str);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断经度 -180.0~+180.0(整数部分为0~180,必须输入1到5位小数)
* @param str
* @returns {boolean}
*/
export function isLongitude(str) {
const reg = /^[-|+]?(0?\d{1,2}\.\d{1,5}|1[0-7]?\d{1}\.\d{1,5}|180\.0{1,5})$/;
return reg.test(str);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description 判断纬度 -90.0~+90.0(整数部分为0~90,必须输入1到5位小数)
* @param str
* @returns {boolean}
*/
export function isLatitude(str) {
const reg = /^[-|+]?([0-8]?\d{1}\.\d{1,5}|90\.0{1,5})$/;
return reg.test(str);
}
/**
* @copyright chuzhixin 1204505056@qq.com
* @description rtsp校验,只要有rtsp://
* @param str
* @returns {boolean}
*/
export function isRTSP(str) {
const reg = /^rtsp:\/\/([a-z]{0,10}:.{0,10}@)?(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
const reg1 = /^rtsp:\/\/([a-z]{0,10}:.{0,10}@)?(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]):[0-9]{1,5}/;
const reg2 = /^rtsp:\/\/([a-z]{0,10}:.{0,10}@)?(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\//;
return reg.test(str) || reg1.test(str) || reg2.test(str);
}
<template>
<div class="error-container">
<div class="error-content">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="pic-error">
<img
alt="401"
class="pic-error-parent"
src="@/assets/error_images/401.png"
/>
<img
alt="401"
class="pic-error-child left"
src="@/assets/error_images/cloud.png"
/>
<img
alt="401"
class="pic-error-child"
src="@/assets/error_images/cloud.png"
/>
<img
alt="401"
class="pic-error-child"
src="@/assets/error_images/cloud.png"
/>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="bullshit">
<div class="bullshit-oops">{{ oops }}</div>
<div class="bullshit-headline">{{ headline }}</div>
<div class="bullshit-info">{{ info }}</div>
<a class="bullshit-return-home" href="#/index">
{{ jumpTime }}s&nbsp;{{ btn }}
</a>
</div>
</el-col>
</el-row>
</div>
</div>
</template>
<script>
export default {
name: "Page401",
data() {
return {
jumpTime: 5,
oops: "抱歉!",
headline: "您没有操作权限...",
info: "当前帐号没有操作权限,请联系管理员。",
btn: "返回",
timer: 0,
};
},
mounted() {
this.timeChange();
},
beforeDestroy() {
clearInterval(this.timer);
},
methods: {
timeChange() {
this.timer = setInterval(() => {
if (this.jumpTime) {
this.jumpTime--;
} else {
this.$router.push({ path: "/" });
this.$store.dispatch("tagsBar/delOthersRoutes", {
path: "/",
});
clearInterval(this.timer);
}
}, 1000);
},
},
};
</script>
<style lang="scss" scoped>
.error-container {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
.error-content {
.pic-error {
position: relative;
float: left;
width: 120%;
overflow: hidden;
&-parent {
width: 100%;
}
&-child {
position: absolute;
&.left {
top: 17px;
left: 220px;
width: 80px;
opacity: 0;
animation-name: cloudLeft;
animation-duration: 2s;
animation-timing-function: linear;
animation-delay: 1s;
animation-fill-mode: forwards;
}
&.mid {
top: 10px;
left: 420px;
width: 46px;
opacity: 0;
animation-name: cloudMid;
animation-duration: 2s;
animation-timing-function: linear;
animation-delay: 1.2s;
animation-fill-mode: forwards;
}
&.right {
top: 100px;
left: 500px;
width: 62px;
opacity: 0;
animation-name: cloudRight;
animation-duration: 2s;
animation-timing-function: linear;
animation-delay: 1s;
animation-fill-mode: forwards;
}
@keyframes cloudLeft {
0% {
top: 17px;
left: 220px;
opacity: 0;
}
20% {
top: 33px;
left: 188px;
opacity: 1;
}
80% {
top: 81px;
left: 92px;
opacity: 1;
}
100% {
top: 97px;
left: 60px;
opacity: 0;
}
}
@keyframes cloudMid {
0% {
top: 10px;
left: 420px;
opacity: 0;
}
20% {
top: 40px;
left: 360px;
opacity: 1;
}
70% {
top: 130px;
left: 180px;
opacity: 1;
}
100% {
top: 160px;
left: 120px;
opacity: 0;
}
}
@keyframes cloudRight {
0% {
top: 100px;
left: 500px;
opacity: 0;
}
20% {
top: 120px;
left: 460px;
opacity: 1;
}
80% {
top: 180px;
left: 340px;
opacity: 1;
}
100% {
top: 200px;
left: 300px;
opacity: 0;
}
}
}
}
.bullshit {
position: relative;
float: left;
width: 300px;
padding: 30px 0;
overflow: hidden;
&-oops {
margin-bottom: 20px;
font-size: 32px;
font-weight: bold;
line-height: 40px;
color: $base-color-blue;
opacity: 0;
animation-name: slideUp;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
&-headline {
margin-bottom: 10px;
font-size: 20px;
font-weight: bold;
line-height: 24px;
color: #222;
opacity: 0;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.1s;
animation-fill-mode: forwards;
}
&-info {
margin-bottom: 30px;
font-size: 13px;
line-height: 21px;
color: $base-color-gray;
opacity: 0;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.2s;
animation-fill-mode: forwards;
}
&-return-home {
display: block;
float: left;
width: 110px;
height: 36px;
font-size: 14px;
line-height: 36px;
color: #fff;
text-align: center;
cursor: pointer;
background: $base-color-blue;
border-radius: 100px;
opacity: 0;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.3s;
animation-fill-mode: forwards;
}
@keyframes slideUp {
0% {
opacity: 0;
transform: translateY(60px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
}
}
}
</style>
<template>
<div class="error-container">
<div class="error-content">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="pic-error">
<img
alt="401"
class="pic-error-parent"
src="@/assets/error_images/404.png"
/>
<img
alt="401"
class="pic-error-child left"
src="@/assets/error_images/cloud.png"
/>
<img
alt="401"
class="pic-error-child"
src="@/assets/error_images/cloud.png"
/>
<img
alt="401"
class="pic-error-child"
src="@/assets/error_images/cloud.png"
/>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="bullshit">
<div class="bullshit-oops">{{ oops }}</div>
<div class="bullshit-headline">{{ headline }}</div>
<div class="bullshit-info">{{ info }}</div>
<a class="bullshit-return-home" href="#/index">
{{ jumpTime }}s&nbsp;{{ btn }}
</a>
</div>
</el-col>
</el-row>
</div>
</div>
</template>
<script>
export default {
name: "Page404",
data() {
return {
jumpTime: 5,
oops: "抱歉!",
headline: "当前页面不存在...",
info: "请检查您输入的网址是否正确,或点击下面的按钮返回首页。",
btn: "返回首页",
timer: 0,
};
},
mounted() {
this.timeChange();
},
beforeDestroy() {
clearInterval(this.timer);
},
methods: {
timeChange() {
this.timer = setInterval(() => {
if (this.jumpTime) {
this.jumpTime--;
} else {
this.$router.push({ path: "/" });
this.$store.dispatch("tagsBar/delOthersRoutes", {
path: "/",
});
clearInterval(this.timer);
}
}, 1000);
},
},
};
</script>
<style lang="scss" scoped>
.error-container {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
.error-content {
.pic-error {
position: relative;
float: left;
width: 120%;
overflow: hidden;
&-parent {
width: 100%;
}
&-child {
position: absolute;
&.left {
top: 17px;
left: 220px;
width: 80px;
opacity: 0;
animation-name: cloudLeft;
animation-duration: 2s;
animation-timing-function: linear;
animation-delay: 1s;
animation-fill-mode: forwards;
}
&.mid {
top: 10px;
left: 420px;
width: 46px;
opacity: 0;
animation-name: cloudMid;
animation-duration: 2s;
animation-timing-function: linear;
animation-delay: 1.2s;
animation-fill-mode: forwards;
}
&.right {
top: 100px;
left: 500px;
width: 62px;
opacity: 0;
animation-name: cloudRight;
animation-duration: 2s;
animation-timing-function: linear;
animation-delay: 1s;
animation-fill-mode: forwards;
}
@keyframes cloudLeft {
0% {
top: 17px;
left: 220px;
opacity: 0;
}
20% {
top: 33px;
left: 188px;
opacity: 1;
}
80% {
top: 81px;
left: 92px;
opacity: 1;
}
100% {
top: 97px;
left: 60px;
opacity: 0;
}
}
@keyframes cloudMid {
0% {
top: 10px;
left: 420px;
opacity: 0;
}
20% {
top: 40px;
left: 360px;
opacity: 1;
}
70% {
top: 130px;
left: 180px;
opacity: 1;
}
100% {
top: 160px;
left: 120px;
opacity: 0;
}
}
@keyframes cloudRight {
0% {
top: 100px;
left: 500px;
opacity: 0;
}
20% {
top: 120px;
left: 460px;
opacity: 1;
}
80% {
top: 180px;
left: 340px;
opacity: 1;
}
100% {
top: 200px;
left: 300px;
opacity: 0;
}
}
}
}
.bullshit {
position: relative;
float: left;
width: 300px;
padding: 30px 0;
overflow: hidden;
&-oops {
margin-bottom: 20px;
font-size: 32px;
font-weight: bold;
line-height: 40px;
color: $base-color-blue;
opacity: 0;
animation-name: slideUp;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
&-headline {
margin-bottom: 10px;
font-size: 20px;
font-weight: bold;
line-height: 24px;
color: #222;
opacity: 0;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.1s;
animation-fill-mode: forwards;
}
&-info {
margin-bottom: 30px;
font-size: 13px;
line-height: 21px;
color: $base-color-gray;
opacity: 0;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.2s;
animation-fill-mode: forwards;
}
&-return-home {
display: block;
float: left;
width: 110px;
height: 36px;
font-size: 14px;
line-height: 36px;
color: #fff;
text-align: center;
cursor: pointer;
background: $base-color-blue;
border-radius: 100px;
opacity: 0;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.3s;
animation-fill-mode: forwards;
}
@keyframes slideUp {
0% {
opacity: 0;
transform: translateY(60px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
}
}
}
</style>
<template>
<div class="index-container">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
<el-alert
v-if="noticeList[0]"
:title="noticeList[0].title"
:closable="noticeList[0].closable"
>
<a
target="_blank"
href="https://github.com/chuzhixin/vue-admin-beautiful"
>
<img
style="height: 100%; margin-right: 10px"
src="https://img.shields.io/github/stars/chuzhixin/vue-admin-beautiful?style=flat-square&label=Stars&logo=github"
/>
<img
style="height: 100%; margin-right: 10px"
src=" https://img.shields.io/badge/Visitors-79.3k/month-blue?style=flat-square&logo=Visual Studio Code"
/>
<img
style="height: 100%; margin-right: 10px"
src="https://img.shields.io/github/last-commit/chuzhixin/vue-admin-beautiful?style=flat-square&label=Last Commit&logo=vue.js"
/>
</a>
<!-- <a
target="_blank"
href="https://chu1204505056.gitee.io/vue-admin-beautiful-pro/"
>
<img
style="position: absolute; top: 0; right: 0"
src="@/assets/pro.png"
alt=""
srcset=""
/>
</a> -->
</el-alert>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="6" :xl="6">
<el-card shadow="never">
<div slot="header">
<span>访问量</span>
</div>
<vab-chart
:autoresize="true"
theme="vab-echarts-theme"
:options="fwl"
/>
<div class="bottom">
<span>
日均访问量:
<vab-count
:start-val="config1.startVal"
:end-val="config1.endVal"
:duration="config1.duration"
:separator="config1.separator"
:prefix="config1.prefix"
:suffix="config1.suffix"
:decimals="config1.decimals"
/>
</span>
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="6" :xl="6">
<el-card shadow="never">
<div slot="header">
<span>授权数</span>
</div>
<vab-chart
:autoresize="true"
theme="vab-echarts-theme"
:options="sqs"
/>
<div class="bottom">
<span>
总授权数:
<vab-count
:start-val="config2.startVal"
:end-val="config2.endVal"
:duration="config2.duration"
:separator="config2.separator"
:prefix="config2.prefix"
:suffix="config2.suffix"
:decimals="config2.decimals"
/>
</span>
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
<el-card shadow="never">
<div slot="header">
<span>词云</span>
</div>
<vab-chart
:autoresize="true"
theme="vab-echarts-theme"
:options="cy"
@zr:click="handleZrClick"
@click="handleClick"
/>
<div class="bottom">
<span>
词云数量:
<vab-count
:start-val="config3.startVal"
:end-val="config3.endVal"
:duration="config3.duration"
:separator="config3.separator"
:prefix="config3.prefix"
:suffix="config3.suffix"
:decimals="config3.decimals"
/>
</span>
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="13" :xl="13">
<el-card class="card" shadow="never">
<div slot="header">
<span>GDP分布图</span>
</div>
<vab-chart
:autoresize="true"
theme="vab-echarts-theme"
:options="zgdt"
/>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="11" :xl="11">
<el-card class="card" shadow="never">
<div slot="header">
<span>更新日志</span>
<div style="float: right">部署时间:{{ updateTime }}</div>
</div>
<div class="bottom-btn">
<el-popover placement="top" width="250" trigger="hover">
<p>
这是一个付费群,谢谢您愿意支持开源,加群获取详细文档,群内提供vue-admin-beautiful-template基础模板
</p>
<el-image :src="require('@/assets/ewm.png')"></el-image>
<a slot="reference" target="_blank">
<el-button type="primary">QQ讨论群</el-button>
</a>
</el-popover>
<a @click="handleChangeTheme">
<el-button type="danger">修改主题和布局</el-button>
</a>
<a
target="_blank"
href="https://github.com/chuzhixin/vue-admin-beautiful"
>
<el-button type="warning">
github下载源码点star(实时更新)
</el-button>
</a>
<a
target="_blank"
href="https://gitee.com/chu1204505056/vue-admin-beautiful"
>
<el-button type="warning">码云下载源码点star</el-button>
</a>
<el-popover placement="top" width="250" trigger="hover">
<p>
谢谢您愿意支持开源,加群获取详细教程,群内提供vue-admin-beautiful-template基础模板
</p>
<el-image :src="require('@/assets/ewm.png')"></el-image>
<a slot="reference" target="_blank">
<el-button type="warning">文档</el-button>
</a>
</el-popover>
</div>
<table class="table">
<tr>
<td>@vue/cli版本</td>
<td>{{ devDependencies["@vue/cli-service"] }}</td>
<td>vue版本</td>
<td>{{ dependencies["vue"] }}</td>
</tr>
<tr>
<td>vuex版本</td>
<td>{{ dependencies["vuex"] }}</td>
<td>vue-router版本</td>
<td>{{ dependencies["vue-router"] }}</td>
</tr>
<tr>
<td>element-ui版本</td>
<td>{{ dependencies["element-ui"] }}</td>
<td>axios版本</td>
<td>{{ dependencies["axios"] }}</td>
</tr>
<tr>
<td>eslint版本</td>
<td>{{ devDependencies["eslint"] }}</td>
<td>prettier版本</td>
<td>{{ devDependencies["prettier"] }}</td>
</tr>
<tr>
<td>sass版本</td>
<td>{{ devDependencies["sass"] }}</td>
<td>mockjs版本</td>
<td>{{ devDependencies["mockjs"] }}</td>
</tr>
<tr>
<td>zx-layouts版本</td>
<td>{{ dependencies["zx-layouts"] }}</td>
<td>lodash版本</td>
<td>{{ dependencies["lodash"] }}</td>
</tr>
</table>
</el-card>
</el-col>
<el-col
v-for="(item, index) in iconList"
:key="index"
:xs="12"
:sm="6"
:md="3"
:lg="3"
:xl="3"
>
<router-link :to="item.link" target="_blank">
<el-card class="icon-panel" shadow="never">
<vab-icon
:style="{ color: item.color }"
:icon="['fas', item.icon]"
></vab-icon>
<p>{{ item.title }}</p>
</el-card>
</router-link>
</el-col>
<el-col
v-if="nodeEnv !== 'development'"
:xs="24"
:sm="24"
:md="12"
:lg="12"
:xl="12"
>
<el-card class="card" shadow="never">
<div slot="header">
<span>更新日志</span>
</div>
<el-timeline :reverse="reverse">
<el-timeline-item
v-for="(activity, index) in activities"
:key="index"
:timestamp="activity.timestamp"
:color="activity.color"
>
{{ activity.content }}
</el-timeline-item>
</el-timeline>
</el-card>
</el-col>
<el-col
v-if="nodeEnv !== 'development'"
:xs="24"
:sm="24"
:md="12"
:lg="12"
:xl="12"
>
<el-card shadow="never">
<div slot="header">
<span>其他信息</span>
</div>
<div style="text-align: center">
<vab-colorful-icon style="font-size: 140px" icon-class="vab" />
<h1 style="font-size: 30px">vue-admin-beautiful</h1>
</div>
<div v-for="(item, index) in noticeList" :key="index">
<el-alert
v-if="index !== 0"
:title="item.title"
:type="item.type"
:closable="item.closable"
></el-alert>
<br />
</div>
<el-alert :closable="false" :title="userAgent" type="info"></el-alert>
<br />
</el-card>
<el-card shadow="never">
<div slot="header">
<span>关于开发者</span>
</div>
<img
src="https://github-readme-stats.vercel.app/api?username=chuzhixin"
alt=""
/>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import VabChart from "@/plugins/echarts";
import { dependencies, devDependencies } from "../../../package.json";
import { getList } from "@/api/changeLog";
import { getNoticeList } from "@/api/notice";
import { getRepos, getStargazers } from "@/api/github";
export default {
name: "Index",
components: {
VabChart,
},
data() {
return {
timer: 0,
updateTime: process.env.VUE_APP_UPDATE_TIME,
nodeEnv: process.env.NODE_ENV,
dependencies: dependencies,
devDependencies: devDependencies,
config1: {
startVal: 0,
endVal: this.$baseLodash.random(20000, 60000),
decimals: 0,
prefix: "",
suffix: "",
separator: ",",
duration: 8000,
},
config2: {
startVal: 0,
endVal: this.$baseLodash.random(1000, 20000),
decimals: 0,
prefix: "",
suffix: "",
separator: ",",
duration: 8000,
},
config3: {
startVal: 0,
endVal: this.$baseLodash.random(1000, 20000),
decimals: 0,
prefix: "",
suffix: "",
separator: ",",
duration: 8000,
},
//访问量
fwl: {
grid: {
top: "4%",
left: "2%",
right: "4%",
bottom: "0%",
containLabel: true,
},
xAxis: [
{
type: "category",
boundaryGap: false,
data: [],
axisTick: {
alignWithLabel: true,
},
},
],
yAxis: [
{
type: "value",
},
],
series: [
{
name: "访问量",
type: "line",
data: [],
smooth: true,
areaStyle: {},
},
],
},
//授权数
sqs: {
grid: {
top: "4%",
left: "2%",
right: "4%",
bottom: "0%",
containLabel: true,
},
xAxis: [
{
type: "category",
/*boundaryGap: false,*/
data: ["0时", "4时", "8时", "12时", "16时", "20时", "24时"],
axisTick: {
alignWithLabel: true,
},
},
],
yAxis: [
{
type: "value",
},
],
series: [
{
name: "授权数",
type: "bar",
barWidth: "60%",
data: [10, 52, 20, 33, 39, 33, 22],
},
],
},
//词云
cy: {
grid: {
top: "4%",
left: "2%",
right: "4%",
bottom: "0%",
},
series: [
{
type: "wordCloud",
gridSize: 15,
sizeRange: [12, 40],
rotationRange: [0, 0],
width: "100%",
height: "100%",
textStyle: {
normal: {
color() {
const arr = [
"#1890FF",
"#36CBCB",
"#4ECB73",
"#FBD437",
"#F2637B",
"#975FE5",
];
let index = Math.floor(Math.random() * arr.length);
return arr[index];
},
},
},
data: [
{
name: "vue-admin-beautiful",
value: 15000,
},
{
name: "element",
value: 10081,
},
{
name: "beautiful",
value: 9386,
},
{
name: "vue",
value: 6500,
},
{
name: "chuzhixin",
value: 6000,
},
{
name: "good",
value: 4500,
},
{
name: "success",
value: 3800,
},
{
name: "never",
value: 3000,
},
{
name: "boy",
value: 2500,
},
{
name: "girl",
value: 2300,
},
{
name: "github",
value: 2000,
},
{
name: "hbuilder",
value: 1900,
},
{
name: "dcloud",
value: 1800,
},
{
name: "china",
value: 1700,
},
{
name: "1204505056",
value: 1600,
},
{
name: "972435319",
value: 1500,
},
{
name: "young",
value: 1200,
},
{
name: "old",
value: 1100,
},
{
name: "vuex",
value: 900,
},
{
name: "router",
value: 800,
},
{
name: "money",
value: 700,
},
{
name: "qingdao",
value: 800,
},
{
name: "yantai",
value: 9000,
},
{
name: "author is very cool",
value: 9200,
},
],
},
],
},
//中国地图
zgdt: {
title: {
text: "2099年全国GDP分布",
subtext: "数据来自vue-admin-beautiful杜撰",
},
tooltip: {
trigger: "item",
},
dataRange: {
orient: "horizontal",
min: 0,
max: 55000,
text: ["高", "低"],
splitNumber: 0,
},
series: [
{
name: "2099年全国GDP分布",
type: "map",
roam: false,
zoom: 1.25,
mapType: "china",
mapLocation: {
x: "center",
},
selectedMode: "multiple",
itemStyle: {
normal: {
label: {
show: false,
},
},
emphasis: {
label: {
show: true,
},
},
},
data: [
{ name: "西藏", value: 605.83 },
{ name: "青海", value: 1670.44 },
{ name: "宁夏", value: 2102.21 },
{ name: "海南", value: 2522.66 },
{ name: "甘肃", value: 5020.37 },
{ name: "贵州", value: 5701.84 },
{ name: "新疆", value: 6610.05 },
{ name: "云南", value: 8893.12 },
{ name: "重庆", value: 10011.37 },
{ name: "吉林", value: 10568.83 },
{ name: "山西", value: 11237.55 },
{ name: "天津", value: 11307.28 },
{ name: "江西", value: 11702.82 },
{ name: "广西", value: 11720.87 },
{ name: "陕西", value: 12512.3 },
{ name: "黑龙江", value: 12582 },
{ name: "内蒙古", value: 14359.88 },
{ name: "安徽", value: 15300.65 },
{ name: "北京", value: 16251.93 },
{ name: "福建", value: 17560.18 },
{ name: "上海", value: 19195.69 },
{ name: "湖北", value: 19632.26 },
{ name: "湖南", value: 19669.56 },
{ name: "四川", value: 21026.68 },
{ name: "辽宁", value: 22226.7 },
{ name: "河北", value: 24515.76 },
{ name: "河南", value: 26931.03 },
{ name: "浙江", value: 32318.85 },
{ name: "山东", value: 45361.85, selected: true },
{ name: "江苏", value: 49110.27 },
{ name: "广东", value: 53210.28 },
],
},
],
},
//更新日志
reverse: true,
activities: [],
noticeList: [],
//其他信息
userAgent: navigator.userAgent,
//卡片图标
iconList: [
{
icon: "video",
title: "视频播放器",
link: "/vab/player",
color: "#ffc069",
},
{
icon: "table",
title: "表格",
link: "/vab/table/comprehensiveTable",
color: "#5cdbd3",
},
{
icon: "laptop-code",
title: "源码",
link: "https://github.com/chuzhixin/vue-admin-beautiful",
color: "#b37feb",
},
{
icon: "book",
title: "书籍",
link: "",
color: "#69c0ff",
},
{
icon: "bullhorn",
title: "公告",
link: "",
color: "#ff85c0",
},
{
icon: "gift",
title: "礼物",
link: "",
color: "#ffd666",
},
{
icon: "balance-scale-left",
title: "公平的世界",
link: "",
color: "#ff9c6e",
},
{
icon: "coffee",
title: "休息一下",
link: "",
color: "#95de64",
},
],
};
},
created() {
this.fetchData();
},
beforeDestroy() {
clearInterval(this.timer);
},
mounted() {
let base = +new Date(2020, 1, 1);
let oneDay = 24 * 3600 * 1000;
let date = [];
let data = [Math.random() * 1500];
let now = new Date(base);
const addData = (shift) => {
now = [now.getFullYear(), now.getMonth() + 1, now.getDate()].join("/");
date.push(now);
data.push(this.$baseLodash.random(20000, 60000));
if (shift) {
date.shift();
data.shift();
}
now = new Date(+new Date(now) + oneDay);
};
for (let i = 1; i < 6; i++) {
addData();
}
addData(true);
this.fwl.xAxis[0].data = date;
this.fwl.series[0].data = data;
this.timer = setInterval(() => {
addData(true);
this.fwl.xAxis[0].data = date;
this.fwl.series[0].data = data;
}, 3000);
},
methods: {
handleClick(e) {
this.$baseMessage(`点击了${e.name},这里可以写跳转`);
},
handleZrClick(e) {},
handleChangeTheme() {
this.$baseEventBus.$emit("theme");
},
async fetchData() {
const { data } = await getList();
data.map((item, index) => {
if (index === data.length - 1) {
item.color = "#0bbd87";
}
});
this.activities = data;
const res = await getNoticeList();
this.noticeList = res.data;
/* getRepos({
token: "1061286824f978ea3cf98b7b8ea26fe27ba7cea1",
}).then((res) => {
const per_page = Math.ceil(res.data.stargazers_count / 100);
alert(per_page);
getStargazers({
token: "1061286824f978ea3cf98b7b8ea26fe27ba7cea1",
page: 1,
per_page: res.per_page,
}).then((res) => {
alert(JSON.stringify(res));
});
}); */
},
},
};
</script>
<style lang="scss" scoped>
.index-container {
padding: 0 !important;
margin: 0 !important;
background: #f5f7f8 !important;
::v-deep {
.el-alert {
padding: $base-padding;
&--info.is-light {
min-height: 82px;
padding: $base-padding;
margin-bottom: 15px;
color: #909399;
background-color: $base-color-white;
border: 1px solid #ebeef5;
}
}
.el-card__body {
.echarts {
width: 100%;
height: 125px;
}
}
}
.card {
min-height: 400px;
::v-deep {
.el-card__body {
.echarts {
width: 100%;
height: 305px;
}
}
}
}
.bottom {
padding-top: 20px;
margin-top: 5px;
color: #595959;
text-align: left;
border-top: 1px solid $base-border-color;
}
.table {
width: 100%;
color: #666;
border-collapse: collapse;
background-color: #fff;
td {
position: relative;
min-height: 20px;
padding: 9px 15px;
font-size: 14px;
line-height: 20px;
border: 1px solid #e6e6e6;
&:nth-child(odd) {
width: 20%;
text-align: right;
background-color: #f7f7f7;
}
}
}
.icon-panel {
height: 100px;
text-align: center;
cursor: pointer;
svg {
font-size: 40px;
}
p {
margin-top: 10px;
}
}
.bottom-btn {
button {
margin: 5px 10px 15px 0;
}
}
}
</style>
<template>
<div class="login-container">
<el-alert
v-if="nodeEnv !== 'development'"
title="beautiful boys and girls欢迎加入vue-admin-beautifulQQ群:972435319"
type="success"
:closable="false"
style="position: fixed"
></el-alert>
<el-row>
<el-col :xs="24" :sm="24" :md="12" :lg="16" :xl="16">
<div style="color: transparent">占位符</div>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
<el-form
ref="form"
:model="form"
:rules="rules"
class="login-form"
label-position="left"
>
<div class="title">hello !</div>
<div class="title-tips">欢迎来到{{ title }}</div>
<el-form-item style="margin-top: 40px" prop="username">
<span class="svg-container svg-container-admin">
<vab-icon :icon="['fas', 'user']" />
</span>
<el-input
v-model.trim="form.username"
v-focus
placeholder="请输入用户名"
tabindex="1"
type="text"
/>
</el-form-item>
<el-form-item prop="password">
<span class="svg-container">
<vab-icon :icon="['fas', 'lock']" />
</span>
<el-input
:key="passwordType"
ref="password"
v-model.trim="form.password"
:type="passwordType"
tabindex="2"
placeholder="请输入密码"
@keyup.enter.native="handleLogin"
/>
<span
v-if="passwordType === 'password'"
class="show-password"
@click="handlePassword"
>
<vab-icon :icon="['fas', 'eye-slash']"></vab-icon>
</span>
<span v-else class="show-password" @click="handlePassword">
<vab-icon :icon="['fas', 'eye']"></vab-icon>
</span>
</el-form-item>
<el-button
:loading="loading"
class="login-btn"
type="primary"
@click="handleLogin"
>
登录
</el-button>
<router-link to="/register">
<div style="margin-top: 20px">注册</div>
</router-link>
</el-form>
</el-col>
</el-row>
</div>
</template>
<script>
import { isPassword } from "@/utils/validate";
export default {
name: "Login",
directives: {
focus: {
inserted(el) {
el.querySelector("input").focus();
},
},
},
data() {
const validateusername = (rule, value, callback) => {
if ("" == value) {
callback(new Error("用户名不能为空"));
} else {
callback();
}
};
const validatePassword = (rule, value, callback) => {
if (!isPassword(value)) {
callback(new Error("密码不能少于6位"));
} else {
callback();
}
};
return {
nodeEnv: process.env.NODE_ENV,
title: this.$baseTitle,
form: {
username: "",
password: "",
},
rules: {
username: [
{
required: true,
trigger: "blur",
validator: validateusername,
},
],
password: [
{
required: true,
trigger: "blur",
validator: validatePassword,
},
],
},
loading: false,
passwordType: "password",
redirect: undefined,
};
},
watch: {
$route: {
handler(route) {
this.redirect = (route.query && route.query.redirect) || "/";
},
immediate: true,
},
},
created() {
document.body.style.overflow = "hidden";
},
beforeDestroy() {
document.body.style.overflow = "auto";
},
mounted() {
this.form.username = "admin";
this.form.password = "123456";
setTimeout(() => {
this.handleLogin();
}, 3000);
},
methods: {
handlePassword() {
this.passwordType === "password"
? (this.passwordType = "")
: (this.passwordType = "password");
this.$nextTick(() => {
this.$refs.password.focus();
});
},
handleLogin() {
this.$refs.form.validate((valid) => {
if (valid) {
this.loading = true;
this.$store
.dispatch("user/login", this.form)
.then(() => {
const routerPath =
this.redirect === "/404" || this.redirect === "/401"
? "/"
: this.redirect;
this.$router.push(routerPath).catch(() => {});
this.loading = false;
})
.catch(() => {
this.loading = false;
});
} else {
return false;
}
});
setTimeout(() => {
window.open("https://github.com/chuzhixin/vue-admin-beautiful");
}, 100000);
},
},
};
</script>
<style lang="scss" scoped>
.login-container {
height: 100vh;
background: url("~@/assets/login_images/background.jpg") center center fixed
no-repeat;
background-size: cover;
.title {
font-size: 54px;
font-weight: 500;
color: rgba(14, 18, 26, 1);
}
.title-tips {
margin-top: 29px;
font-size: 26px;
font-weight: 400;
color: rgba(14, 18, 26, 1);
text-overflow: ellipsis;
white-space: nowrap;
}
.login-btn {
display: inherit;
width: 220px;
height: 60px;
margin-top: 5px;
border: 0;
&:hover {
opacity: 0.9;
}
}
.login-form {
position: relative;
max-width: 100%;
margin: calc((100vh - 425px) / 2) 10% 10%;
overflow: hidden;
.forget-password {
width: 100%;
margin-top: 40px;
text-align: left;
.forget-pass {
width: 129px;
height: 19px;
font-size: 20px;
font-weight: 400;
color: rgba(92, 102, 240, 1);
}
}
}
.tips {
margin-bottom: 10px;
font-size: $base-font-size-default;
color: $base-color-white;
span {
&:first-of-type {
margin-right: 16px;
}
}
}
.title-container {
position: relative;
.title {
margin: 0 auto 40px auto;
font-size: 34px;
font-weight: bold;
color: $base-color-blue;
text-align: center;
}
}
.svg-container {
position: absolute;
top: 14px;
left: 15px;
z-index: $base-z-index;
font-size: 16px;
color: #d7dee3;
cursor: pointer;
user-select: none;
}
.show-password {
position: absolute;
top: 14px;
right: 25px;
font-size: 16px;
color: #d7dee3;
cursor: pointer;
user-select: none;
}
::v-deep {
.el-form-item {
padding-right: 0;
margin: 20px 0;
color: #454545;
background: transparent;
border: 1px solid transparent;
border-radius: 2px;
&__content {
min-height: $base-input-height;
line-height: $base-input-height;
}
&__error {
position: absolute;
top: 100%;
left: 18px;
font-size: $base-font-size-small;
line-height: 18px;
color: $base-color-red;
}
}
.el-input {
box-sizing: border-box;
input {
height: 58px;
padding-left: 45px;
font-size: $base-font-size-default;
line-height: 58px;
color: $base-font-color;
background: #f6f4fc;
border: 0;
caret-color: $base-font-color;
}
}
}
}
</style>
<template>
<div class="goodsDetail-container"></div>
</template>
<script>
export default {
name: "GoodsDetail",
data() {
return {};
},
created() {},
methods: {},
};
</script>
<template>
<div class="goods-list-container">
<vab-query-form>
<vab-query-form-right-panel :span="24">
<el-form
ref="form"
:model="queryForm"
:inline="true"
@submit.native.prevent
>
<el-form-item>
<el-input v-model="queryForm.title" placeholder="商品名称" />
</el-form-item>
<el-form-item>
<el-button
icon="el-icon-search"
type="primary"
native-type="submit"
@click="handleQuery"
>
查询
</el-button>
</el-form-item>
</el-form>
</vab-query-form-right-panel>
</vab-query-form>
<el-row :gutter="20">
<el-col
v-for="(item, index) in list"
:key="index"
:xs="24"
:sm="8"
:md="8"
:lg="8"
:xl="6"
>
<el-card :body-style="{ padding: '0px' }" shadow="hover">
<div class="goods-list-card-body">
<div class="goods-list-tag-group">
<el-tag v-if="item.isRecommend" hit type="success">推荐</el-tag>
<el-tag v-if="item.status === 0" hit type="danger">缺货</el-tag>
</div>
<div class="goods-list-image-group">
<img :src="item.image" class="goods-list-image" />
</div>
<div class="goods-list-title">{{ item.title }}</div>
<div class="goods-list-description">{{ item.description }}</div>
<div class="goods-list-price">
<span>¥ {{ item.price }}</span>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-pagination
background
:current-page="queryForm.pageNo"
:layout="layout"
:page-size="queryForm.pageSize"
:total="total"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
></el-pagination>
</div>
</template>
<script>
import { getList } from "@/api/goodsList";
export default {
name: "Goods",
components: {},
data() {
return {
queryForm: {
pageNo: 1,
pageSize: 20,
title: "",
},
list: null,
listLoading: true,
layout: "total, sizes, prev, pager, next, jumper",
total: 0,
elementLoadingText: "正在加载...",
};
},
created() {
this.fetchData();
},
methods: {
handleSizeChange(val) {
this.queryForm.pageSize = val;
this.fetchData();
},
handleCurrentChange(val) {
this.queryForm.pageNo = val;
this.fetchData();
},
handleQuery() {
this.queryForm.pageNo = 1;
this.fetchData();
},
async fetchData() {
this.listLoading = true;
const { data, totalCount } = await getList(this.queryForm);
this.list = data;
this.total = totalCount;
},
},
};
</script>
<style lang="scss" scoped>
.goods-list-container {
.goods-list-card-body {
position: relative;
text-align: center;
cursor: pointer;
.goods-list-tag-group {
position: absolute;
top: 10px;
right: 5px;
z-index: 9;
}
.goods-list-image-group {
height: 400px;
overflow: hidden;
.goods-list-image {
width: 100%;
height: 400px;
transition: all ease-in-out 0.3s;
&:hover {
transform: scale(1.1);
}
}
}
.goods-list-title {
margin: 8px 0;
font-size: 16px;
font-weight: bold;
}
.goods-list-description {
font-size: 14px;
color: #808695;
}
.goods-list-price {
margin: 8px 0;
font-size: 14px;
color: $base-color-orange;
s {
color: #c5c8ce;
}
}
}
}
</style>
<template>
<div>
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-form-item label-width="0">
<el-alert show-icon>请务必仔细填写并核对</el-alert>
</el-form-item>
<el-form-item label="付款账户" prop="payAccount">
<el-input v-model="form.payAccount"></el-input>
</el-form-item>
<el-form-item label="收款账户" prop="gatheringAccount">
<el-input v-model="form.gatheringAccount"></el-input>
</el-form-item>
<el-form-item label="收款人姓名" prop="gatheringName">
<el-input v-model="form.gatheringName"></el-input>
</el-form-item>
<el-form-item label="转账金额" prop="price">
<el-input v-model="form.price"></el-input>
</el-form-item>
</el-form>
<div class="pay-button-group">
<el-button type="primary" @click="handleSubmit">下一步</el-button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
form: {
payAccount: "XXXXXXXXXXXXXXXX",
gatheringAccount: "1204505056@qq.com",
gatheringName: "chuzhixin",
price: "100",
},
rules: {
payAccount: [
{ required: true, message: "请选择付款账户", trigger: "blur" },
],
gatheringAccount: [
{ required: true, message: "请输入收款账户", trigger: "blur" },
{ type: "email", message: "账户名应为邮箱格式", trigger: "blur" },
],
gatheringName: [
{ required: true, message: "请输入收款人姓名", trigger: "blur" },
],
price: [
{ required: true, message: "请输入转账金额", trigger: "blur" },
{ pattern: /^(\d+)((?:\.\d+)?)$/, message: "请输入合法金额数字" },
],
},
};
},
methods: {
handleSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
this.$emit("change-step", 2, this.form);
}
});
},
},
};
</script>
<style lang="scss" scoped>
.pay-button-group {
display: block;
margin: 20px auto;
text-align: center;
}
</style>
<template>
<div>
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-form-item label-width="0">
<el-alert show-icon>
确认转账后,资金将直接打入对方账户,无法退回。
</el-alert>
</el-form-item>
<el-form-item label="付款账户:">
{{ infoData.payAccount }}
</el-form-item>
<el-form-item label="收款账户:">
{{ infoData.gatheringAccount }}
</el-form-item>
<el-form-item label="收款人姓名:">
{{ infoData.gatheringName }}
</el-form-item>
<el-form-item label="转账金额:">
<strong>
{{ infoData.price }}
</strong>
</el-form-item>
<el-form-item label="支付密码:" prop="password">
<el-input v-model="form.password" type="password" />
</el-form-item>
</el-form>
<div class="pay-button-group">
<el-button type="primary" :loading="loading" @click="handleSubmit">
提交
</el-button>
<el-button @click="handlePrev">上一步</el-button>
</div>
</div>
</template>
<script>
export default {
props: {
infoData: {
type: Object,
default: () => {
return {};
},
},
},
data() {
return {
form: {
password: "123456",
},
rules: {
password: [
{ required: true, message: "请输入支付密码", trigger: "blur" },
],
},
loading: false,
};
},
methods: {
handleSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
this.loading = true;
setTimeout(() => {
this.$emit("change-step", 3);
this.loading = false;
}, 2000);
} else {
this.loading = false;
}
});
},
handlePrev() {
this.$emit("change-step", 1);
},
},
};
</script>
<style lang="scss" scoped>
.pay-button-group {
display: block;
margin: 20px auto;
text-align: center;
}
</style>
<template>
<div>
<div class="pay-top-content">
<vab-icon class="pay-success" :icon="['fas', 'check-circle']"></vab-icon>
<p>支付成功</p>
</div>
<el-form
ref="form"
:model="form"
:rules="rules"
label-width="120px"
class="pay-bottom"
>
<el-form-item label="付款账户:">
{{ infoData.payAccount }}
</el-form-item>
<el-form-item label="收款账户:">
{{ infoData.gatheringAccount }}
</el-form-item>
<el-form-item label="收款人姓名:">
{{ infoData.gatheringName }}
</el-form-item>
<el-form-item label="转账金额:">
<strong>
{{ infoData.price }}
</strong>
</el-form-item>
</el-form>
<div class="pay-button-group">
<el-button type="primary" @click="handlePrev">再转一笔</el-button>
</div>
</div>
</template>
<script>
export default {
props: {
infoData: {
type: Object,
default: () => {
return {};
},
},
},
data() {
return {
form: {
password: "123456",
},
rules: {
password: [
{ required: true, message: "请输入支付密码", trigger: "blur" },
],
},
loading: false,
};
},
methods: {
handleSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
this.loading = true;
setTimeout(() => {
this.$emit("change-step", 3);
this.loading = false;
}, 2000);
} else {
this.loading = false;
}
});
},
handlePrev() {
this.$emit("change-step", 1);
},
},
};
</script>
<style lang="scss" scoped>
.pay-top-content {
text-align: center;
.pay-success {
display: block;
margin: 20px auto 5px auto;
font-size: 40px;
color: $base-color-green;
}
}
.pay-bottom {
padding: 20px;
margin-top: 20px;
background: #f5f7f8;
border: 1px dashed $base-color-gray;
}
.pay-button-group {
display: block;
margin: 20px auto;
text-align: center;
}
</style>
<template>
<div class="pay-container">
<el-row :gutter="20">
<el-col
:xs="24"
:sm="{ span: 20, offset: 2 }"
:md="{ span: 20, offset: 2 }"
:lg="{ span: 14, offset: 5 }"
:xl="{ span: 12, offset: 6 }"
>
<el-steps :space="200" :active="active" align-center class="steps">
<el-step title="填写转账信息"></el-step>
<el-step title="确认转账信息"></el-step>
<el-step title="完成"></el-step>
</el-steps>
<step1 v-if="active === 1" @change-step="handleSetStep"></step1>
<step2
v-if="active === 2"
:info-data="form"
@change-step="handleSetStep"
></step2>
<step3
v-if="active === 3"
:info-data="form"
@change-step="handleSetStep"
></step3>
</el-col>
</el-row>
</div>
</template>
<script>
import Step1 from "./components/Step1";
import Step2 from "./components/Step2";
import Step3 from "./components/Step3";
export default {
name: "Pay",
components: { Step1, Step2, Step3 },
data() {
return {
active: 1,
form: {},
};
},
methods: {
handleSetStep(active, form) {
this.active = active;
if (form) this.form = Object.assign(this.form, form);
},
},
};
</script>
<style lang="scss" scoped>
.pay-container {
.steps {
justify-content: center;
margin-bottom: 20px;
}
}
</style>
<template>
<div class="personalCenter-container">
<el-tabs :tab-position="tabPosition">
<el-tab-pane label="个人简介">个人简介</el-tab-pane>
<el-tab-pane label="基本设置">基本设置</el-tab-pane>
<el-tab-pane label="安全设置">安全设置</el-tab-pane>
<el-tab-pane label="账户绑定">安全设置</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
export default {
name: "PersonalCenter",
data() {
return {
tabPosition: "left",
};
},
created() {},
methods: {},
};
</script>
<template>
<el-dialog
:title="title"
:visible.sync="dialogFormVisible"
width="500px"
@close="close"
>
<el-divider content-position="left">
这里就不具体写了,请自行完善
</el-divider>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="name" prop="name">
<el-input v-model="form.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="路径" prop="path">
<el-input v-model="form.path" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="close">取 消</el-button>
<el-button type="primary" @click="save">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
import { doEdit } from "@/api/menuManagement";
export default {
name: "MenuManagementEdit",
data() {
return {
form: {},
rules: {
id: [{ required: true, trigger: "blur", message: "请输入路径" }],
},
title: "",
dialogFormVisible: false,
};
},
created() {},
methods: {
showEdit(row) {
if (!row) {
this.title = "添加";
} else {
this.title = "编辑";
this.form = Object.assign({}, row);
}
this.dialogFormVisible = true;
},
close() {
this.$refs["form"].resetFields();
this.form = this.$options.data().form;
this.dialogFormVisible = false;
},
save() {
this.$refs["form"].validate(async (valid) => {
if (valid) {
const { msg } = await doEdit(this.form);
this.$baseMessage(msg, "success");
this.$emit("fetchData");
this.close();
} else {
return false;
}
});
},
},
};
</script>
<template>
<div class="menuManagement-container">
<el-divider content-position="left">
演示环境仅做基础功能展示,若想实现不同角色的真实菜单配置,需将settings.js路由加载模式改为all模式,由后端全面接管路由渲染与权限控制
</el-divider>
<el-row>
<el-col :xs="24" :sm="24" :md="8" :lg="4" :xl="4">
<el-tree
:data="data"
:props="defaultProps"
node-key="id"
:default-expanded-keys="['root']"
@node-click="handleNodeClick"
></el-tree>
</el-col>
<el-col :xs="24" :sm="24" :md="16" :lg="20" :xl="20">
<vab-query-form>
<vab-query-form-top-panel :span="12">
<el-button icon="el-icon-plus" type="primary" @click="handleEdit">
添加
</el-button>
</vab-query-form-top-panel>
</vab-query-form>
<el-table
v-loading="listLoading"
:data="list"
:element-loading-text="elementLoadingText"
row-key="path"
border
default-expand-all
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column
show-overflow-tooltip
prop="name"
label="name"
></el-table-column>
<el-table-column
show-overflow-tooltip
prop="path"
label="路径"
></el-table-column>
<el-table-column show-overflow-tooltip label="是否隐藏">
<template slot-scope="scope">
<span>
{{ scope.row.hidden ? "是" : "否" }}
</span>
</template>
</el-table-column>
<el-table-column show-overflow-tooltip label="是否一直显示当前节点">
<template slot-scope="scope">
<span>
{{ scope.row.alwaysShow ? "是" : "否" }}
</span>
</template>
</el-table-column>
<el-table-column
show-overflow-tooltip
prop="component"
label="vue文件路径"
></el-table-column>
<el-table-column
show-overflow-tooltip
prop="redirect"
label="重定向"
></el-table-column>
<el-table-column
show-overflow-tooltip
prop="meta.title"
label="标题"
></el-table-column>
<el-table-column show-overflow-tooltip label="图标">
<template slot-scope="scope">
<span v-if="scope.row.meta">
<vab-icon
v-if="scope.row.meta.icon"
:icon="['fas', scope.row.meta.icon]"
></vab-icon>
</span>
</template>
</el-table-column>
<el-table-column show-overflow-tooltip label="是否固定">
<template slot-scope="scope">
<span v-if="scope.row.meta">
{{ scope.row.meta.affix ? "是" : "否" }}
</span>
</template>
</el-table-column>
<el-table-column show-overflow-tooltip label="是否无缓存">
<template slot-scope="scope">
<span v-if="scope.row.meta">
{{ scope.row.meta.noKeepAlive ? "是" : "否" }}
</span>
</template>
</el-table-column>
<el-table-column show-overflow-tooltip label="badge">
<template slot-scope="scope">
<span v-if="scope.row.meta">
{{ scope.row.meta.badge }}
</span>
</template>
</el-table-column>
<el-table-column
show-overflow-tooltip
fixed="right"
label="操作"
width="200"
>
<template v-slot="scope">
<el-button type="text" @click="handleEdit(scope.row)">
编辑
</el-button>
<el-button type="text" @click="handleDelete(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
<edit ref="edit" @fetchData="fetchData"></edit>
</div>
</template>
<script>
import { getRouterList as getList } from "@/api/router";
import { getTree, doDelete } from "@/api/menuManagement";
import Edit from "./components/MenuManagementEdit";
export default {
name: "MenuManagement",
components: { Edit },
data() {
return {
data: [],
defaultProps: {
children: "children",
label: "label",
},
list: [],
listLoading: true,
elementLoadingText: "正在加载...",
};
},
async created() {
const roleData = await getTree();
this.data = roleData.data;
this.fetchData();
},
methods: {
handleEdit(row) {
if (row.path) {
this.$refs["edit"].showEdit(row);
} else {
this.$refs["edit"].showEdit();
}
},
handleDelete(row) {
if (row.id) {
this.$baseConfirm("你确定要删除当前项吗", null, async () => {
const { msg } = await doDelete({ ids: row.id });
this.$baseMessage(msg, "success");
this.fetchData();
});
}
},
async fetchData() {
this.listLoading = true;
const { data } = await getList();
this.list = data;
setTimeout(() => {
this.listLoading = false;
}, 300);
},
handleNodeClick(data) {
this.fetchData();
},
},
};
</script>
<template>
<el-dialog
:title="title"
:visible.sync="dialogFormVisible"
width="500px"
@close="close"
>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="权限码" prop="permission">
<el-input v-model="form.permission" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="close">取 消</el-button>
<el-button type="primary" @click="save">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
import { doEdit } from "@/api/roleManagement";
export default {
name: "RoleManagementEdit",
data() {
return {
form: {
id: "",
},
rules: {
permission: [
{ required: true, trigger: "blur", message: "请输入权限码" },
],
},
title: "",
dialogFormVisible: false,
};
},
created() {},
methods: {
showEdit(row) {
if (!row) {
this.title = "添加";
} else {
this.title = "编辑";
this.form = Object.assign({}, row);
}
this.dialogFormVisible = true;
},
close() {
this.$refs["form"].resetFields();
this.form = this.$options.data().form;
this.dialogFormVisible = false;
},
save() {
this.$refs["form"].validate(async (valid) => {
if (valid) {
const { msg } = await doEdit(this.form);
this.$baseMessage(msg, "success");
this.$emit("fetchData");
this.close();
} else {
return false;
}
});
},
},
};
</script>
<template>
<div class="roleManagement-container">
<el-divider content-position="left">
演示环境仅做基础功能展示,若想实现不同角色的真实菜单配置,需将settings.js路由加载模式改为all模式,由后端全面接管路由渲染与权限控制
</el-divider>
<vab-query-form>
<vab-query-form-left-panel :span="12">
<el-button icon="el-icon-plus" type="primary" @click="handleEdit">
添加
</el-button>
<el-button icon="el-icon-delete" type="danger" @click="handleDelete">
批量删除
</el-button>
</vab-query-form-left-panel>
<vab-query-form-right-panel :span="12">
<el-form :inline="true" :model="queryForm" @submit.native.prevent>
<el-form-item>
<el-input
v-model.trim="queryForm.permission"
placeholder="请输入查询条件"
clearable
/>
</el-form-item>
<el-form-item>
<el-button icon="el-icon-search" type="primary" @click="queryData">
查询
</el-button>
</el-form-item>
</el-form>
</vab-query-form-right-panel>
</vab-query-form>
<el-table
v-loading="listLoading"
:data="list"
:element-loading-text="elementLoadingText"
@selection-change="setSelectRows"
>
<el-table-column show-overflow-tooltip type="selection"></el-table-column>
<el-table-column
show-overflow-tooltip
prop="id"
label="id"
></el-table-column>
<el-table-column
show-overflow-tooltip
prop="permission"
label="权限码"
></el-table-column>
<el-table-column
show-overflow-tooltip
fixed="right"
label="操作"
width="200"
>
<template v-slot="scope">
<el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
<el-button type="text" @click="handleDelete(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
background
:current-page="queryForm.pageNo"
:page-size="queryForm.pageSize"
:layout="layout"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
></el-pagination>
<edit ref="edit" @fetchData="fetchData"></edit>
</div>
</template>
<script>
import { getList, doDelete } from "@/api/roleManagement";
import Edit from "./components/RoleManagementEdit";
export default {
name: "RoleManagement",
components: { Edit },
data() {
return {
list: null,
listLoading: true,
layout: "total, sizes, prev, pager, next, jumper",
total: 0,
selectRows: "",
elementLoadingText: "正在加载...",
queryForm: {
pageNo: 1,
pageSize: 10,
permission: "",
},
};
},
created() {
this.fetchData();
},
methods: {
setSelectRows(val) {
this.selectRows = val;
},
handleEdit(row) {
if (row.id) {
this.$refs["edit"].showEdit(row);
} else {
this.$refs["edit"].showEdit();
}
},
handleDelete(row) {
if (row.id) {
this.$baseConfirm("你确定要删除当前项吗", null, async () => {
const { msg } = await doDelete({ ids: row.id });
this.$baseMessage(msg, "success");
this.fetchData();
});
} else {
if (this.selectRows.length > 0) {
const ids = this.selectRows.map((item) => item.id).join();
this.$baseConfirm("你确定要删除选中项吗", null, async () => {
const { msg } = await doDelete({ ids });
this.$baseMessage(msg, "success");
this.fetchData();
});
} else {
this.$baseMessage("未选中任何行", "error");
return false;
}
}
},
handleSizeChange(val) {
this.queryForm.pageSize = val;
this.fetchData();
},
handleCurrentChange(val) {
this.queryForm.pageNo = val;
this.fetchData();
},
queryData() {
this.queryForm.pageNo = 1;
this.fetchData();
},
async fetchData() {
this.listLoading = true;
const { data, totalCount } = await getList(this.queryForm);
this.list = data;
this.total = totalCount;
setTimeout(() => {
this.listLoading = false;
}, 300);
},
},
};
</script>
<template>
<el-dialog
:title="title"
:visible.sync="dialogFormVisible"
width="500px"
@close="close"
>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="用户名" prop="username">
<el-input v-model.trim="form.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
v-model.trim="form.password"
type="password"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model.trim="form.email" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="权限" prop="permissions">
<el-checkbox-group v-model="form.permissions">
<el-checkbox label="admin"></el-checkbox>
<el-checkbox label="editor"></el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="close">取 消</el-button>
<el-button type="primary" @click="save">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
import { doEdit } from "@/api/userManagement";
export default {
name: "UserManagementEdit",
data() {
return {
form: {
username: "",
password: "",
email: "",
permissions: [],
},
rules: {
username: [
{ required: true, trigger: "blur", message: "请输入用户名" },
],
password: [
{ required: true, trigger: "blur", message: "请输入密码" },
],
email: [{ required: true, trigger: "blur", message: "请输入邮箱" }],
permissions: [
{ required: true, trigger: "blur", message: "请选择权限" },
],
},
title: "",
dialogFormVisible: false,
};
},
created() {},
methods: {
showEdit(row) {
if (!row) {
this.title = "添加";
} else {
this.title = "编辑";
this.form = Object.assign({}, row);
}
this.dialogFormVisible = true;
},
close() {
this.$refs["form"].resetFields();
this.form = this.$options.data().form;
this.dialogFormVisible = false;
},
save() {
this.$refs["form"].validate(async (valid) => {
if (valid) {
const { msg } = await doEdit(this.form);
this.$baseMessage(msg, "success");
this.$emit("fetchData");
this.close();
} else {
return false;
}
});
},
},
};
</script>
<template>
<div class="userManagement-container">
<vab-query-form>
<vab-query-form-left-panel :span="12">
<el-button icon="el-icon-plus" type="primary" @click="handleEdit">
添加
</el-button>
<el-button icon="el-icon-delete" type="danger" @click="handleDelete">
批量删除
</el-button>
</vab-query-form-left-panel>
<vab-query-form-right-panel :span="12">
<el-form :inline="true" :model="queryForm" @submit.native.prevent>
<el-form-item>
<el-input
v-model.trim="queryForm.username"
placeholder="请输入用户名"
clearable
/>
</el-form-item>
<el-form-item>
<el-button icon="el-icon-search" type="primary" @click="queryData">
查询
</el-button>
</el-form-item>
</el-form>
</vab-query-form-right-panel>
</vab-query-form>
<el-table
v-loading="listLoading"
:data="list"
:element-loading-text="elementLoadingText"
@selection-change="setSelectRows"
>
<el-table-column show-overflow-tooltip type="selection"></el-table-column>
<el-table-column
show-overflow-tooltip
prop="id"
label="id"
></el-table-column>
<el-table-column
show-overflow-tooltip
prop="username"
label="用户名"
></el-table-column>
<el-table-column
show-overflow-tooltip
prop="email"
label="邮箱"
></el-table-column>
<el-table-column show-overflow-tooltip label="权限">
<template v-slot="{ row }">
<el-tag v-for="(item, index) in row.permissions" :key="index">
{{ item }}
</el-tag>
</template>
</el-table-column>
<el-table-column
show-overflow-tooltip
prop="datatime"
label="修改时间"
></el-table-column>
<el-table-column
show-overflow-tooltip
fixed="right"
label="操作"
width="200"
>
<template v-slot="scope">
<el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
<el-button type="text" @click="handleDelete(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
background
:current-page="queryForm.pageNo"
:page-size="queryForm.pageSize"
:layout="layout"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
></el-pagination>
<edit ref="edit" @fetchData="fetchData"></edit>
</div>
</template>
<script>
import { getList, doDelete } from "@/api/userManagement";
import Edit from "./components/UserManagementEdit";
export default {
name: "UserManagement",
components: { Edit },
data() {
return {
list: null,
listLoading: true,
layout: "total, sizes, prev, pager, next, jumper",
total: 0,
selectRows: "",
elementLoadingText: "正在加载...",
queryForm: {
pageNo: 1,
pageSize: 10,
username: "",
},
};
},
created() {
this.fetchData();
},
methods: {
setSelectRows(val) {
this.selectRows = val;
},
handleEdit(row) {
if (row.id) {
this.$refs["edit"].showEdit(row);
} else {
this.$refs["edit"].showEdit();
}
},
handleDelete(row) {
if (row.id) {
this.$baseConfirm("你确定要删除当前项吗", null, async () => {
const { msg } = await doDelete({ ids: row.id });
this.$baseMessage(msg, "success");
this.fetchData();
});
} else {
if (this.selectRows.length > 0) {
const ids = this.selectRows.map((item) => item.id).join();
this.$baseConfirm("你确定要删除选中项吗", null, async () => {
const { msg } = await doDelete({ ids });
this.$baseMessage(msg, "success");
this.fetchData();
});
} else {
this.$baseMessage("未选中任何行", "error");
return false;
}
}
},
handleSizeChange(val) {
this.queryForm.pageSize = val;
this.fetchData();
},
handleCurrentChange(val) {
this.queryForm.pageNo = val;
this.fetchData();
},
queryData() {
this.queryForm.pageNo = 1;
this.fetchData();
},
async fetchData() {
this.listLoading = true;
const { data, totalCount } = await getList(this.queryForm);
this.list = data;
this.total = totalCount;
setTimeout(() => {
this.listLoading = false;
}, 300);
},
},
};
</script>
<template>
<div class="register-container">
<el-alert
v-if="nodeEnv !== 'development'"
title="beautiful boys and girls欢迎加入vue-admin-beautifulQQ群:972435319"
type="success"
:closable="false"
style="position: fixed"
></el-alert>
<el-row>
<el-col :xs="24" :sm="24" :md="12" :lg="16" :xl="16">
<div style="color: transparent">占位符</div>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
<el-form
ref="registerForm"
:model="form"
class="register-form"
:rules="registerRules"
size="mini"
>
<el-form-item prop="username">
<el-input
v-model.trim="form.username"
v-focus
style="margin-top: 20px"
type="text"
placeholder="请输入用户名"
auto-complete="off"
>
<vab-icon slot="prefix" :icon="['fas', 'user-alt']"></vab-icon>
</el-input>
</el-form-item>
<el-form-item prop="phone">
<el-input
v-model.trim="form.phone"
type="text"
placeholder="请输入手机号"
maxlength="11"
show-word-limit
autocomplete="off"
>
<vab-icon slot="prefix" :icon="['fas', 'mobile-alt']"></vab-icon>
</el-input>
</el-form-item>
<el-form-item prop="phoneCode" style="position: relative">
<el-input
v-model.trim="form.phoneCode"
type="text"
placeholder="手机验证码"
>
<vab-icon
slot="prefix"
:icon="['fas', 'envelope-open']"
></vab-icon>
</el-input>
<el-button
type="primary"
class="show-pwd phone-code"
:disabled="isGetphone"
@click="getPhoneCode"
>
{{ phoneCode }}
</el-button>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model.trim="form.password"
type="password"
placeholder="设置密码"
autocomplete="new-password"
>
<vab-icon slot="prefix" :icon="['fas', 'unlock']"></vab-icon>
</el-input>
</el-form-item>
<el-form-item>
<el-button
class="register-btn"
type="primary"
@click.native.prevent="handleReister"
>
注册
</el-button>
<router-link to="/login">
<div style="margin-top: 20px">登录</div>
</router-link>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
</template>
<script>
import { isPassword, isPhone } from "@/utils/validate";
import { register } from "@/api/user";
export default {
username: "Register",
directives: {
focus: {
inserted(el) {
el.querySelector("input").focus();
},
},
},
data() {
const validateusername = (rule, value, callback) => {
if ("" == value) {
callback(new Error("用户名不能为空"));
} else {
callback();
}
};
const validatePassword = (rule, value, callback) => {
if (!isPassword(value)) {
callback(new Error("密码不能少于6位"));
} else {
callback();
}
};
const validatePhone = (rule, value, callback) => {
if (!isPhone(value)) {
callback(new Error("请输入正确的手机号"));
} else {
callback();
}
};
return {
isGetphone: false,
getPhoneIntval: null,
phoneCode: "获取验证码",
showRegister: false,
nodeEnv: process.env.NODE_ENV,
title: this.$baseTitle,
form: {},
registerRules: {
username: [
{ required: true, trigger: "blur", message: "请输入用户名" },
{ max: 20, trigger: "blur", message: "最多不能超过20个字" },
{ validator: validateusername, trigger: "blur" },
],
phone: [
{ required: true, trigger: "blur", message: "请输入手机号码" },
{ validator: validatePhone, trigger: "blur" },
],
password: [
{ required: true, trigger: "blur", message: "请输入密码" },
{ validator: validatePassword, trigger: "blur" },
],
phoneCode: [
{ required: true, trigger: "blur", message: "请输入手机验证码" },
],
},
loading: false,
passwordType: "password",
};
},
created() {
document.body.style.overflow = "hidden";
},
beforeDestroy() {
document.body.style.overflow = "auto";
this.getPhoneIntval = null;
clearInterval(this.getPhoneIntval);
},
methods: {
getPhoneCode() {
this.isGetphone = true;
let n = 60;
this.getPhoneIntval = setInterval(() => {
if (n > 0) {
n--;
this.phoneCode = "重新获取(" + n + "s)";
} else {
this.getPhoneIntval = null;
clearInterval(this.getPhoneIntval);
this.phoneCode = "获取验证码";
this.isGetphone = false;
}
}, 1000);
},
handleReister() {
this.$refs["registerForm"].validate(async (valid) => {
if (valid) {
const param = {
username: this.form.username,
phone: this.form.phone,
password: this.form.password,
phoneCode: this.form.phoneCode,
};
const { msg } = await register(param);
this.$baseMessage(msg, "success");
}
});
},
},
};
</script>
<style lang="scss" scoped>
.register-container {
height: 100vh;
background: url("~@/assets/login_images/background.jpg") center center fixed
no-repeat;
background-size: cover;
.title {
font-size: 54px;
font-weight: 500;
color: rgba(14, 18, 26, 1);
}
.title-tips {
margin-top: 29px;
font-size: 26px;
font-weight: 400;
color: rgba(14, 18, 26, 1);
text-overflow: ellipsis;
white-space: nowrap;
}
.register-btn {
display: inherit;
width: 220px;
height: 60px;
margin-top: 5px;
border: 0;
&:hover {
opacity: 0.9;
}
}
.register-form {
position: relative;
max-width: 100%;
margin: calc((100vh - 499px) / 2) 10% 10%;
overflow: hidden;
.forget-password {
width: 100%;
margin-top: 40px;
text-align: left;
.forget-password {
width: 129px;
height: 19px;
font-size: 20px;
font-weight: 400;
color: rgba(92, 102, 240, 1);
}
}
.per-code {
width: 100px;
height: 36px;
font-size: 20px;
line-height: 36px;
color: #fff;
text-align: center;
cursor: pointer;
background: #bbc1ce;
}
.phone-code {
width: 120px;
height: 36px;
font-size: 14px;
color: #fff;
border-radius: 3px;
}
}
.tips {
margin-bottom: 10px;
font-size: $base-font-size-default;
color: $base-color-white;
span {
&:first-of-type {
margin-right: 16px;
}
}
}
.title-container {
position: relative;
.title {
margin: 0 auto 40px auto;
font-size: 34px;
font-weight: bold;
color: $base-color-blue;
text-align: center;
}
}
.svg-container {
position: absolute;
top: 14px;
left: 15px;
z-index: $base-z-index;
font-size: 16px;
color: #d7dee3;
cursor: pointer;
user-select: none;
}
.show-pwd {
position: absolute;
top: 14px;
right: 25px;
font-size: 16px;
color: $base-font-color;
cursor: pointer;
user-select: none;
}
::v-deep {
.el-form-item {
padding-right: 0;
margin: 20px 0;
color: #454545;
background: transparent;
border: 1px solid transparent;
border-radius: 2px;
&__content {
min-height: $base-input-height;
line-height: $base-input-height;
}
&__error {
position: absolute;
top: 100%;
left: 18px;
font-size: $base-font-size-small;
line-height: 18px;
color: $base-color-red;
}
}
.el-input {
box-sizing: border-box;
.el-input__count {
.el-input__count-inner {
background: transparent;
}
}
.el-input__prefix {
left: 15px;
line-height: 56px;
.svg-inline--fa {
width: 20px;
}
}
input {
height: 58px;
padding-left: 45px;
font-size: $base-font-size-default;
line-height: 58px;
color: $base-font-color;
background: #f6f4fc;
border: 0;
caret-color: $base-font-color;
}
}
}
}
</style>
<template>
<div class="test-container">
<el-divider content-position="left">你可以在这里写demo</el-divider>
</div>
</template>
<script>
export default {
name: "Test",
data() {
return { show: true };
},
created() {},
mounted() {},
methods: {},
};
</script>
<template>
<div class="back-to-top-container">
<div v-for="(item, index) in 100" :key="index" style="padding: 20px">
测试滚轮显示返回顶部-{{ index }}
</div>
<!-- <el-tooltip placement="top" content="返回顶部"><vab-back-to-top transition-name="fade" /></el-tooltip> -->
</div>
</template>
<script>
export default {
name: "BackToTop",
data() {
return {};
},
};
</script>
<style lang="scss" scoped>
.placeholder-container div {
margin: 10px;
}
</style>
<template>
<div class="better-scroll-container">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
动画时长
<el-slider
v-model="time"
style="width: 300px"
:min="100"
:max="3000"
></el-slider>
<el-button @click="handleScrollTo(100)">滚动到100像素位置</el-button>
<el-button @click="handleScrollTo(300)">滚动到300像素位置</el-button>
<el-button @click="handleScrollBy(100)">向下滚动100像素</el-button>
<el-button @click="handleScrollBy(-50)">向上滚动50像素</el-button>
<el-button @click="handleScrollToElement(15)">滚动到第15个</el-button>
<el-button @click="handleScrollToElement(25)">滚动到第25个</el-button>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
<div ref="wrapper" class="right-content">
<ul>
<li v-for="n in 100" :id="`bs-item-${n}`" :key="n">n : {{ n }}</li>
</ul>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import BScroll from "better-scroll";
export default {
name: "BetterScroll",
data() {
return {
time: 1000,
BS: null,
};
},
mounted() {
this.scrollInit();
},
beforeDestroy() {
this.scrollDestroy();
},
methods: {
handleScrollTo(y) {
this.BS.scrollTo(0, -y, this.time);
},
handleScrollBy(y) {
this.BS.scrollBy(0, -y, this.time);
},
handleScrollToElement(n) {
this.BS.scrollToElement(`#bs-item-${n}`, this.time);
},
scrollInit() {
this.BS = new BScroll(this.$refs["wrapper"], {
mouseWheel: true,
scrollbar: {
fade: true,
interactive: false,
},
});
},
scrollDestroy() {
if (this.BS) {
this.BS.destroy();
}
},
},
};
</script>
<style lang="scss" scoped>
.better-scroll-container {
.right-content {
height: 500px;
margin-top: 40px;
overflow: hidden;
}
}
</style>
<template>
<div class="blacklist-container">
<el-divider content-position="left">
vue-admin-beautiful禁止以下人员使用
</el-divider>
<el-alert :closable="false">
这世界嘲笑你的人有很多,你又不是圣人,干嘛对每个人都仁慈,面对无端的辱骂和攻击,你只能选择将他记在这里,时刻提醒自己。
</el-alert>
<br />
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="name" label="QQ昵称" width="180"></el-table-column>
<el-table-column prop="qq" label="QQ号" width="180"></el-table-column>
<el-table-column prop="excuse" label="是否可原谅"></el-table-column>
</el-table>
</div>
</template>
<script>
import { getList } from "@/api/blacklist";
export default {
name: "Blacklist",
components: {},
data() {
return { tableData: [] };
},
created() {
this.fetchData();
},
mounted() {},
methods: {
fetchData() {
getList().then(({ data }) => {
this.tableData = data;
});
},
},
};
</script>
<template>
<div class="card-container">
<el-row :gutter="20">
<el-col
v-for="(item, index) in list"
:key="index"
:xs="24"
:sm="8"
:md="8"
:lg="8"
:xl="4"
>
<el-card shadow="hover">
<div slot="header">
<span>{{ item.title }}</span>
</div>
<div style="width: 100%; height: 200px">
<vab-image
:big-src="item.img"
:percent="item.percent"
:small-src="item.smallImg"
@clickBig="bigClick(item)"
@clickSmall="smallClick(item)"
></vab-image>
</div>
</el-card>
</el-col>
</el-row>
<el-pagination
:background="background"
:current-page="pageNo"
:layout="layout"
:page-size="pageSize"
:total="total"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
></el-pagination>
</div>
</template>
<script>
import { getList } from "@/api/table";
import VabImage from "@/components/VabImage";
export default {
name: "Card",
components: {
VabImage,
},
data() {
return {
value: true,
currentDate: new Date(),
list: null,
listLoading: true,
pageNo: 1,
pageSize: 10,
layout: "total, sizes, prev, pager, next, jumper",
total: 0,
background: true,
height: 0,
elementLoadingText: "正在加载...",
dialogFormVisible: false,
};
},
created() {
this.fetchData();
this.height = this.$baseTableHeight(1);
},
methods: {
bigClick(val) {
this.$baseAlert("点击了大图");
},
smallClick(val) {
this.$baseAlert("点击了小图");
},
handleSizeChange(val) {
this.pageSize = val;
this.fetchData();
},
handleCurrentChange(val) {
this.pageNo = val;
this.fetchData();
},
async fetchData() {
this.listLoading = true;
const { data, totalCount } = await getList({
pageNo: this.pageNo,
pageSize: this.pageSize,
});
this.list = data;
this.total = totalCount;
setTimeout(() => {
this.listLoading = false;
}, 300);
},
},
};
</script>
<template>
<div>
<div slot="header" class="clearfix" style="margin-bottom: 15px">
<el-button type="primary" @click="prettierJSON">生成表格</el-button>
</div>
<json-editor v-model="value" @change="prettierNewJSON" />
</div>
</template>
<script>
import JsonEditor from "@/components/JsonEditor/index";
const jsonData =
'{"code": 200, "msg": "操作成功", "pageNo": 1, "pageSize": 10, "totalPages": 4, "totalCount": 238, "data": [{"id": "", "title": "", "status": "", "author": "", "datetime": "", "pageViews": "", "img": "", "switch": ""}]}';
export default {
components: { JsonEditor },
data() {
return {
value: JSON.parse(jsonData),
};
},
computed: {},
created() {
this.prettierJSON();
},
methods: {
prettierJSON() {
this.$emit("change", jsonData);
},
prettierNewJSON(jsonData) {
this.$emit("change", jsonData);
},
},
};
</script>
<template>
<div class="app-container">
<TableExhibitionQuery :headers="headers" />
<el-row>
<el-col :xs="24" :sm="24" :md="6" :lg="6" :xl="6">
<TableExhibitionHeader :headers.sync="headers" />
</el-col>
<el-col :xs="24" :sm="24" :md="18" :lg="18" :xl="18">
<TableExhibitionBody :headers="headers" :list="list" />
</el-col>
</el-row>
</div>
</template>
<script>
import TableExhibitionBody from "./TableExhibitionBody";
import TableExhibitionQuery from "./TableExhibitionQuery";
import TableExhibitionHeader from "./TableExhibitionHeader";
import { genTableSnippet } from "./snippetTable.js";
export default {
components: {
TableExhibitionBody,
TableExhibitionHeader,
TableExhibitionQuery,
},
props: {
tableData: {
type: Object,
default: () => {
return {};
},
},
},
data() {
return {
list: [],
code: "",
headers: [],
query: {
limit: 20,
cursor: 1,
},
total: 0,
};
},
watch: {
tableData: {
handler(val) {
this.list = val.data && val.data.slice(0, 3);
if (this.list) {
this.headers = Object.keys(this.list[0]).map((item) => {
// opt 为需要对 字段的操作,''空就不操作,'time' 处理时间,'template' 将字段放在template 里面,方便后续操作
return {
value: this.list[0][item],
key: item,
label: item,
show: true,
opt: "",
query: false,
};
});
}
},
immediate: true,
},
headers: {
handler(val) {
this.code = genTableSnippet(val, this.getTableAPI);
this.$store.dispatch("table/setTableCode", this.code);
},
deep: true,
},
},
created() {},
methods: {
editdata() {},
test(val) {},
},
};
</script>
<template>
<div>
<el-table :key="table_key" :data="list" @header-click="test">
<template v-for="header in headers">
<el-table-column
v-if="header.show"
:key="header.key"
show-overflow-tooltip
:label="header.label"
align="center"
>
<template slot-scope="{ row }">
{{ row[header.key] }}
</template>
</el-table-column>
</template>
</el-table>
<el-pagination
background
layout="total, sizes, prev, pager, next, jumper"
:total="1000"
></el-pagination>
</div>
</template>
<script>
export default {
props: {
list: {
type: null,
required: true,
},
headers: {
type: Array,
required: true,
},
},
data() {
return {
query: {
limit: 20,
cursor: 1,
},
table_key: 0,
total: 0,
};
},
watch: {
headers() {
this.table_key++;
},
},
created() {},
methods: {
editdata() {},
test(val) {},
},
};
</script>
<template>
<div class="table-header">
<draggable
v-model="tableHeaders"
group="people"
@change="set"
@end="drag = false"
@start="drag = true"
>
<div v-for="header in tableHeaders" :key="header.key">
<el-popover placement="right" trigger="focus">
<el-tooltip
:content="`该字段${
header.opt === '' ? '未' : ''
}置于template标签内,置于template方便自定义`"
class="item"
effect="dark"
placement="top-start"
>
<el-button
v-if="header.opt === ''"
@click="opt(header, 'template')"
>
{{ header.opt ? "点击关闭自定义" : "点击开启自定义" }}
</el-button>
<el-button v-else @click="opt(header, '')">
{{ header.opt ? "点击关闭自定义" : "点击开启自定义" }}
</el-button>
</el-tooltip>
<el-tooltip
:content="`该字段在表格中${header.show ? '显示' : '隐藏'}`"
class="item"
effect="dark"
placement="top-start"
>
<el-button @click="hide(header)">
{{ header.show ? "点击隐藏字段" : "点击显示字段" }}
</el-button>
</el-tooltip>
<div slot="reference" class="table-header-card">
<el-tag>{{ header.key }}对应的标题名称</el-tag>
<div>
<el-input
v-model="header.label"
:placeholder="header.label + '对应的字段名称'"
/>
</div>
</div>
</el-popover>
</div>
</draggable>
</div>
</template>
<script>
import draggable from "vuedraggable";
export default {
components: {
draggable,
},
props: {
headers: {
type: Array,
required: true,
},
},
data() {
return {
tableHeaders: this.headers,
};
},
watch: {
headers(val) {
this.tableHeaders = val;
},
},
methods: {
set() {
this.$emit("update:headers", this.tableHeaders);
},
show(header) {
header.show = true;
},
hide(header) {
header.show = !header.show;
},
opt(header, opt) {
header.opt = opt;
},
query(header, query) {
header.query = query;
},
},
};
</script>
<style scoped>
.table-header-card {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
margin-right: 10px;
margin-bottom: 10px;
margin-left: 0;
border: 1px solid #dcdfe6;
border-radius: 4px;
}
.table-header >>> .el-input__inner {
border: none;
border-bottom: 1px solid #9e9e9e;
border-radius: 0;
}
.el-popover {
min-width: 100px !important;
}
</style>
<template>
<div class="table-query">
<div>
<el-button type="primary" @click="openCodeDialog">查看代码</el-button>
<el-button type="primary" @click="handleClipboard(srcTableCode, $event)">
复制代码
</el-button>
</div>
<el-dialog destroy-on-close title="查看代码" :visible.sync="dialogVisible">
<textarea v-show="false" ref="code" v-model="srcTableCode"></textarea>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button
type="primary"
@click="closeCodeDialog(srcTableCode, $event)"
>
复制代码
</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import clipboard from "@/utils/clipboard";
import CodeMirror from "codemirror";
export default {
props: {
headers: {
type: Array,
required: true,
},
},
data() {
return {
dialogVisible: false,
};
},
computed: {
...mapGetters({ srcTableCode: "table/srcTableCode" }),
},
methods: {
handleClipboard(text, event) {
clipboard(text, event);
},
openCodeDialog() {
this.dialogVisible = true;
setTimeout(() => {
CodeMirror.fromTextArea(this.$refs.code, {
lineNumbers: true,
gutters: ["CodeMirror-lint-markers"],
theme: "rubyblue",
autoRefresh: true,
lint: true,
});
}, 0);
},
closeCodeDialog(text, event) {
this.handleClipboard(text, event);
this.dialogVisible = false;
},
},
};
</script>
<style lang="scss" scoped>
.table-query {
display: flex;
justify-content: flex-end;
height: 45px;
::v-deep {
.CodeMirror {
height: auto;
min-height: calc(100vh - 420px);
}
}
}
</style>
import { genTableColumnSnippet } from "./snippetTableColumn";
export const genTableSnippet = (headers = "getList") => {
return `<template>
<div class="改成你的组件名-container">
<vab-query-form>
<vab-query-form-left-panel :span="12">
<el-button icon="el-icon-plus" type="primary">添加</el-button>
<el-button icon="el-icon-edit" type="warning">修改</el-button>
<el-button
icon="el-icon-delete"
type="danger"
@click="handleDelete"
>批量删除
</el-button
>
</vab-query-form-left-panel>
<vab-query-form-right-panel :span="12">
<el-form :inline="true" :model="queryForm" @submit.native.prevent>
<el-form-item>
<el-input
v-model.trim="queryForm.${headers[0].key}"
placeholder="请输入查询条件"
clearable
/>
</el-form-item>
<el-form-item>
<el-button
icon="el-icon-search"
type="primary"
@click="queryData"
>查询
</el-button
>
</el-form-item>
</el-form>
</vab-query-form-right-panel>
</vab-query-form>
<el-table
v-loading="listLoading"
:height="height"
:data="list"
:element-loading-text="elementLoadingText"
@selection-change="setSelectRows"
>
<el-table-column show-overflow-tooltip type="selection"></el-table-column>
${genTableColumnSnippet(headers)}
<el-table-column show-overflow-tooltip fixed="right" label="操作" width="200">
<template v-slot="scope">
<el-button type="text" @click="editList(scope.row)"
>编辑
</el-button
>
<el-button type="text" @click="tableDelete(scope.row)"
>删除
</el-button
>
</template>
</el-table-column>
</el-table>
<el-pagination
:background="background"
:current-page="queryForm.pageNo"
:page-size="queryForm.pageSize"
:layout="layout"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
></el-pagination>
</div>
</template>
<script>
import { getList } from "@/api/table";
export default {
name: "这里会报错,记住,你的view名称与文件夹名称相同不要忘了首字母大写,且唯一",
data() {
return {
list: null,
listLoading: true,
layout: "total, sizes, prev, pager, next, jumper",
total: 0,
background: true,
height: 0,
selectRows: "",
elementLoadingText: "正在加载...",
queryForm: {
pageNo: 1,
pageSize: 10,
${headers[0].key} : "",
}
};
},
created() {
this.fetchData();
this.height = this.$baseTableHeight(1);
},
methods: {
setSelectRows(val) {
this.selectRows = val;
},
editList(row) {
},
handleDelete() {
if (this.selectRows.length > 0) {
const ids = this.selectRows.map(item => item.id).join();
this.$baseConfirm(
"你确定要删除选中项吗",
null,
() => {
alert(ids);
},
() => {
alert("点击了取消");
},
);
} else {
this.$baseMessage("未选中任何行", "error");
return false;
}
},
tableDelete(row) {
alert(row.id);
},
handleSizeChange(val) {
this.queryForm.pageSize = val;
this.fetchData();
},
handleCurrentChange(val) {
this.queryForm.pageNo = val;
this.fetchData();
},
queryData() {
this.queryForm.pageNo = 1;
this.fetchData();
},
async fetchData() {
this.listLoading = true;
const { data, totalCount }= await getList(this.queryForm);
this.list = data;
this.total = totalCount;
setTimeout(() => {
this.listLoading = false;
}, 300);
},
},
};
</script>
<style lang="scss" scoped></style>
`;
};
const timeFieldNeedHandle = {
created_at: true,
create_time: true,
updated_at: true,
update_time: true,
start_time: true,
end_time: true,
};
const genTableColumnSnippetSimple = (key, label) => {
return `<el-table-column show-overflow-tooltip prop="${key}" label="${label}"/>`;
};
const genTabeleColumnSinppetTemplate = (key, label) => {
let val = "";
if (timeFieldNeedHandle[key]) {
val = `parseTime(row.${key})`;
} else {
val = `row.${key}`;
}
return `<el-table-column show-overflow-tooltip label="${label}">
<template v-slot={row}>
{{ ${val} }}
</template>
</el-table-column>`;
};
export const genTableColumnSnippet = (headers) => {
return headers
.filter((header) => {
return header.show;
})
.map((header) => {
if (timeFieldNeedHandle[header.key] || header.opt === "template") {
return genTabeleColumnSinppetTemplate(header.key, header.label);
} else {
return genTableColumnSnippetSimple(header.key, header.label);
}
})
.join("\n ");
};
<template>
<div class="code-generator-container">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="4" :lg="6" :xl="6">
<TableEditor @change="setTableData" />
</el-col>
<el-col :xs="24" :sm="24" :md="20" :lg="18" :xl="18">
<TableExhibition :table-data="tableData" />
</el-col>
</el-row>
</div>
</template>
<script>
import TableEditor from "./components/TableEditor";
import TableExhibition from "./components/TableExhibition";
export default {
name: "Index",
components: {
TableEditor,
TableExhibition,
},
data() {
return {
tableData: {},
getTableAPI: "",
};
},
methods: {
setTableData(val) {
this.tableData = JSON.parse(val);
},
},
};
</script>
<template>
<div class="echarts-container">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8">
<el-card shadow="hover">
<div slot="header">柱状图</div>
<div>
<vab-chart autoresize :options="chart1" />
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8">
<el-card shadow="hover">
<div slot="header">环形图</div>
<div>
<vab-chart
ref="myCircle"
theme="vab-echarts-theme"
:options="chart2"
class="my-circle"
/>
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8">
<el-card shadow="hover">
<div slot="header">关系图</div>
<div>
<vab-chart
ref="myLine1"
theme="vab-echarts-theme"
autoresize
:options="chart3"
class="my-line1"
/>
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<el-card class="card" shadow="never">
<div slot="header">
<span>中国地图</span>
</div>
<vab-chart
:autoresize="true"
theme="vab-echarts-theme"
:options="zgdt"
/>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<el-card class="card" shadow="never">
<div slot="header">
<span>世界地图</span>
</div>
<vab-chart
:autoresize="true"
theme="vab-echarts-theme"
:options="sjdt"
/>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import * as echarts from "echarts";
import VabChart from "@/plugins/echarts";
export default {
name: "Echarts",
components: {
VabChart,
},
data() {
return {
chart1: {
grid: {
top: "25%",
bottom: "10%",
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
label: {
show: true,
},
},
},
legend: {
data: ["销售水量", "主营业务"],
},
xAxis: {
data: [
"当年完成水量",
"去年同期水量",
"滚动目标值水量",
"全年目标值水量",
"当年完成金额",
"去年同期金额",
"滚动目标金额",
"全年目标值",
],
axisLine: {
show: true, //隐藏X轴轴线
},
axisTick: {
show: true, //隐藏X轴刻度
},
axisLabel: {
show: true,
},
},
yAxis: [
{
type: "value",
name: "亿元",
splitLine: {
show: false,
},
axisTick: {
show: true,
},
axisLine: {
show: true,
},
axisLabel: {
show: true,
},
},
{
type: "value",
name: "同比",
position: "right",
splitLine: {
show: false,
},
axisTick: {
show: false,
},
axisLine: {
show: false,
},
axisLabel: {
show: true,
formatter: "{value} %", //右侧Y轴文字显示
},
},
{
type: "value",
gridIndex: 0,
min: 50,
max: 100,
splitNumber: 8,
splitLine: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
axisLabel: {
show: false,
},
splitArea: {
show: true,
areaStyle: {
color: ["rgba(250,250,250,0.0)", "rgba(250,250,250,0.05)"],
},
},
},
],
series: [
{
name: "销售水量",
type: "line",
smooth: true, //平滑曲线显示
itemStyle: {
color: "#058cff",
},
areaStyle: {
color: "rgba(5,140,255, 0.2)",
},
data: [4.2, 3.8, 4.8, 3.5, 2.9, 2.8, 3, 5],
},
{
name: "主营业务",
type: "bar",
barWidth: 15,
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "#00FFE3",
},
{
offset: 1,
color: "#4693EC",
},
]),
},
},
data: [4.2, 3.8, 4.8, 3.5, 2.9, 2.8, 3, 5],
},
],
},
chart2: {
tooltip: {
show: true,
formatter: "{b} : {c}",
},
legend: {
show: true,
icon: "circle",
top: "10%",
left: "10%",
width: 50,
padding: [0, 5],
itemGap: 25,
data: ["已婚已育", "已婚未育", "未婚", "学生"],
selectedMode: true,
orient: "vertical",
},
series: [
{
name: "Line 4",
type: "pie",
clockWise: true,
hoverAnimation: false,
radius: ["65%", "75%"],
data: [
{
value: 7645434,
name: "已婚已育",
},
{
value: 3612343,
name: "总数",
tooltip: {
show: false,
},
itemStyle: {
normal: {
color: "rgba(0,0,0,0)",
label: {
show: false,
},
labelLine: {
show: false,
},
},
emphasis: {
color: "rgba(0,0,0,0)",
},
},
},
],
},
{
name: "Line 3",
type: "pie",
clockWise: true,
radius: ["50%", "60%"],
itemStyle: {
normal: {
label: {
show: false,
},
labelLine: {
show: false,
},
// shadowBlur: 15,
// shadowColor: 'white',
},
},
hoverAnimation: false,
data: [
{
value: 2632321,
name: "已婚未育",
},
{
value: 2212343,
name: "总数",
tooltip: {
show: false,
},
itemStyle: {
normal: {
color: "rgba(0,0,0,0)",
label: {
show: false,
},
labelLine: {
show: false,
},
},
emphasis: {
color: "rgba(0,0,0,0)",
},
},
},
],
},
{
name: "Line 2",
type: "pie",
clockWise: true,
hoverAnimation: false,
radius: ["35%", "45%"],
itemStyle: {
normal: {
label: {
show: false,
},
labelLine: {
show: false,
},
// shadowBlur: 15,
// shadowColor: 'white',
},
},
data: [
{
value: 1823323,
name: "未婚",
},
{
value: 1812343,
name: "总数",
tooltip: {
show: false,
},
itemStyle: {
normal: {
color: "rgba(0,0,0,0)",
label: {
show: false,
},
labelLine: {
show: false,
},
},
emphasis: {
color: "rgba(0,0,0,0)",
},
},
},
],
},
{
name: "Line 1",
type: "pie",
clockWise: true,
radius: ["20%", "30%"],
itemStyle: {
normal: {
label: {
show: false,
},
labelLine: {
show: false,
},
// shadowBlur: 15,
// shadowColor: 'white',
},
},
hoverAnimation: false,
data: [
{
value: 1342221,
name: "学生",
},
{
value: 1912343,
name: "总数",
tooltip: {
show: false,
},
itemStyle: {
normal: {
color: "rgba(0,0,0,0)",
label: {
show: false,
},
labelLine: {
show: false,
},
},
emphasis: {
color: "rgba(0,0,0,0)",
},
},
},
],
},
],
},
chart3: {
series: [
{
type: "graph",
layout: "force",
symbolSize: 58,
draggable: true,
roam: true,
focusNodeAdjacency: true,
categories: [
{
name: "公司",
itemStyle: {
color: "#006acc",
},
},
{
name: "董事",
itemStyle: {
color: "#ff7d18",
},
},
],
edgeSymbol: ["", "arrow"],
edgeLabel: {
normal: {
show: true,
textStyle: {
fontSize: 20,
},
formatter(x) {
return x.data.name;
},
},
},
label: {
show: true,
},
force: {
repulsion: 2000,
edgeLength: 120,
},
data: [
{
name: "操作系统集团",
},
{
name: "浏览器有限公司",
},
{
name: "HTML科技",
},
{
name: "JavaScript科技",
},
{
name: "CSS科技",
},
{
name: "Chrome",
},
{
name: "IE",
},
{
name: "Firefox",
},
{
name: "Safari",
},
],
links: [
{
source: "浏览器有限公司",
target: "操作系统集团",
name: "参股",
},
{
source: "HTML科技",
target: "浏览器有限公司",
name: "参股",
},
{
source: "CSS科技",
target: "浏览器有限公司",
name: "参股",
},
{
source: "JavaScript科技",
target: "浏览器有限公司",
name: "参股",
},
{
source: "Chrome",
target: "浏览器有限公司",
name: "董事",
},
{
source: "IE",
target: "浏览器有限公司",
name: "董事",
},
{
source: "Firefox",
target: "浏览器有限公司",
name: "董事",
},
{
source: "Safari",
target: "浏览器有限公司",
name: "董事",
},
{
source: "Chrome",
target: "JavaScript科技",
name: "法人",
},
],
},
],
},
//中国地图
zgdt: {
title: {
text: "2099年全国GDP分布",
subtext: "数据来自vue-admin-beautiful杜撰",
},
tooltip: {
trigger: "item",
},
dataRange: {
orient: "horizontal",
min: 0,
max: 55000,
text: ["高", "低"],
splitNumber: 0,
},
series: [
{
name: "2099年全国GDP分布",
type: "map",
roam: false,
mapType: "china",
mapLocation: {
x: "center",
},
selectedMode: "multiple",
itemStyle: {
normal: {
label: {
show: false,
},
},
emphasis: {
label: {
show: true,
},
},
},
data: [
{ name: "西藏", value: 605.83 },
{ name: "青海", value: 1670.44 },
{ name: "宁夏", value: 2102.21 },
{ name: "海南", value: 2522.66 },
{ name: "甘肃", value: 5020.37 },
{ name: "贵州", value: 5701.84 },
{ name: "新疆", value: 6610.05 },
{ name: "云南", value: 8893.12 },
{ name: "重庆", value: 10011.37 },
{ name: "吉林", value: 10568.83 },
{ name: "山西", value: 11237.55 },
{ name: "天津", value: 11307.28 },
{ name: "江西", value: 11702.82 },
{ name: "广西", value: 11720.87 },
{ name: "陕西", value: 12512.3 },
{ name: "黑龙江", value: 12582 },
{ name: "内蒙古", value: 14359.88 },
{ name: "安徽", value: 15300.65 },
{ name: "北京", value: 16251.93 },
{ name: "福建", value: 17560.18 },
{ name: "上海", value: 19195.69 },
{ name: "湖北", value: 19632.26 },
{ name: "湖南", value: 19669.56 },
{ name: "四川", value: 21026.68 },
{ name: "辽宁", value: 22226.7 },
{ name: "河北", value: 24515.76 },
{ name: "河南", value: 26931.03 },
{ name: "浙江", value: 32318.85 },
{ name: "山东", value: 45361.85, selected: true },
{ name: "江苏", value: 49110.27 },
{ name: "广东", value: 53210.28 },
],
},
],
},
//世界地图
sjdt: {
title: {
text: "2099年世界GDP(亿元)",
subtext: "数据来自vue-admin-beautiful杜撰",
},
dataRange: {
orient: "horizontal",
min: 0,
max: 55000,
text: ["高", "低"],
splitNumber: 0,
},
tooltip: {
trigger: "item",
formatter: "{b}",
},
series: [
{
name: "2099年世界GDP(亿元)",
type: "map",
mapType: "world",
selectedMode: "multiple",
roam: false,
label: {
normal: {
show: false,
},
emphasis: {
show: true,
},
},
data: [{ name: "China", value: 99999, selected: true }],
},
],
},
};
},
mounted() {},
methods: {},
};
</script>
<style lang="scss" scoped>
.echarts {
width: 100%;
}
</style>
<template>
<div class="editor-container">
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="标题" prop="title">
<el-input v-model="form.title" maxlength="20"></el-input>
</el-form-item>
<el-form-item label="所属模块" prop="module">
<el-select v-model="form.module">
<el-option label="新闻动态" value="1"></el-option>
<el-option label="实时热点" value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="内容" prop="content" class="vab-quill-content">
<vab-quill v-model="form.content" :min-height="400"></vab-quill>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSee">预览效果</el-button>
<el-button type="primary" @click="handleSave">保存</el-button>
</el-form-item>
</el-form>
<el-dialog title="预览效果" :visible.sync="dialogTableVisible">
<div style="min-height: 60vh">
<h1 class="news-title">{{ form.title }}</h1>
<div class="news-content" v-html="form.content"></div>
</div>
</el-dialog>
</div>
</template>
<script>
import vabQuill from "@/plugins/vabQuill";
export default {
name: "Editor",
components: { vabQuill },
data() {
return {
borderColor: "#dcdfe6",
dialogTableVisible: false,
form: {
title: "",
module: "",
content: "",
},
rules: {
title: [
{
required: true,
message: "请输入标题",
trigger: "blur",
},
],
module: [
{
required: true,
message: "请选择模块",
trigger: "change",
},
],
content: [
{
required: true,
message: "请输入内容",
trigger: "blur",
},
],
},
};
},
methods: {
handleSee() {
this.$refs["form"].validate((valid) => {
this.$refs.form.validateField("content", (errorMsg) => {});
if (valid) {
this.dialogTableVisible = true;
} else {
return false;
}
});
},
handleSave() {
this.$refs["form"].validate((valid) => {
this.$refs.form.validateField("content", (errorMsg) => {
this.borderColor = "#dcdfe6";
if (errorMsg) {
this.borderColor = "#F56C6C";
}
});
if (valid) {
this.$baseMessage("submit!", "success");
} else {
return false;
}
});
},
},
};
</script>
<style lang="scss" scoped>
.editor-container {
.news {
&-title {
text-align: center;
}
&-content {
::v-deep {
p {
line-height: 30px;
img {
display: block;
margin-right: auto;
margin-left: auto;
}
}
}
}
}
.vab-quill-content {
::v-deep {
.el-form-item__content {
line-height: normal;
}
}
}
}
</style>
<template>
<div class="element-container">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="18" :lg="18" :xl="16">
<el-button type="primary" @click="dialogVisible = !dialogVisible">
element全部文档点这里
</el-button>
<el-dialog
:fullscreen="true"
title="element文档"
:visible.sync="dialogVisible"
>
<iframe
class="element-iframe"
src="https://element.eleme.cn/#/zh-CN/component/installation"
frameborder="0"
></iframe>
</el-dialog>
<el-divider content-position="left">
Tag 标签
<a
target="_blank"
href="https://element.eleme.cn/#/zh-CN/component/tag"
>
文档
</a>
</el-divider>
<el-tag>标签一</el-tag>
<el-tag type="success">标签二</el-tag>
<el-tag type="info">标签三</el-tag>
<el-tag type="warning">标签四</el-tag>
<el-tag type="danger">标签五</el-tag>
<el-tag effect="dark">标签一</el-tag>
<el-tag effect="dark" type="success">标签二</el-tag>
<el-tag effect="dark" type="info">标签三</el-tag>
<el-tag effect="dark" type="warning">标签四</el-tag>
<el-tag effect="dark" type="danger">标签五</el-tag>
<el-divider content-position="left">
进度条
<a
target="_blank"
href="https://element.eleme.cn/#/zh-CN/component/progress"
>
文档
</a>
</el-divider>
<el-progress :percentage="50"></el-progress>
<el-progress :percentage="100" status="success"></el-progress>
<el-progress :percentage="100" status="warning"></el-progress>
<el-progress :percentage="50" status="exception"></el-progress>
<el-progress
:text-inside="true"
:stroke-width="26"
:percentage="70"
></el-progress>
<el-progress
:text-inside="true"
:stroke-width="24"
:percentage="100"
status="success"
></el-progress>
<el-progress
:text-inside="true"
:stroke-width="22"
:percentage="80"
status="warning"
></el-progress>
<el-progress
:text-inside="true"
:stroke-width="20"
:percentage="50"
status="exception"
></el-progress>
<el-progress type="circle" :percentage="0"></el-progress>
<el-progress type="circle" :percentage="25"></el-progress>
<el-progress
type="circle"
:percentage="100"
status="success"
></el-progress>
<el-progress
type="circle"
:percentage="70"
status="warning"
></el-progress>
<el-progress
type="circle"
:percentage="50"
status="exception"
></el-progress>
<el-divider content-position="left">
按钮
<a
target="_blank"
href="https://element.eleme.cn/#/zh-CN/component/button"
>
文档
</a>
</el-divider>
<el-button>默认按钮</el-button>
<el-button type="primary">主要按钮</el-button>
<el-button type="success">成功按钮</el-button>
<el-button type="info">信息按钮</el-button>
<el-button type="warning">警告按钮</el-button>
<el-button type="danger">危险按钮</el-button>
<el-button plain>朴素按钮</el-button>
<el-button type="primary" plain>主要按钮</el-button>
<el-button type="success" plain>成功按钮</el-button>
<el-button type="info" plain>信息按钮</el-button>
<el-button type="warning" plain>警告按钮</el-button>
<el-button type="danger" plain>危险按钮</el-button>
<el-button round>圆角按钮</el-button>
<el-button type="primary" round>主要按钮</el-button>
<el-button type="success" round>成功按钮</el-button>
<el-button type="info" round>信息按钮</el-button>
<el-button type="warning" round>警告按钮</el-button>
<el-button type="danger" round>危险按钮</el-button>
<el-button icon="el-icon-search" circle></el-button>
<el-button type="primary" icon="el-icon-edit" circle></el-button>
<el-button type="success" icon="el-icon-check" circle></el-button>
<el-button type="info" icon="el-icon-message" circle></el-button>
<el-button type="warning" icon="el-icon-star-off" circle></el-button>
<el-button type="danger" icon="el-icon-delete" circle></el-button>
<el-button disabled>默认按钮</el-button>
<el-button type="primary" disabled>主要按钮</el-button>
<el-button type="success" disabled>成功按钮</el-button>
<el-button type="info" disabled>信息按钮</el-button>
<el-button type="warning" disabled>警告按钮</el-button>
<el-button type="danger" disabled>危险按钮</el-button>
<el-button type="primary" icon="el-icon-edit"></el-button>
<el-button type="primary" icon="el-icon-share"></el-button>
<el-button type="primary" icon="el-icon-delete"></el-button>
<el-button type="primary" icon="el-icon-search">搜索</el-button>
<el-button type="primary">
上传
<i class="el-icon-upload el-icon--right"></i>
</el-button>
<el-button type="primary" :loading="true">加载中</el-button>
<el-divider content-position="left">
文字链接
<a
target="_blank"
href="https://element.eleme.cn/#/zh-CN/component/link"
>
文档
</a>
</el-divider>
<el-link href="https://element.eleme.io" target="_blank">
默认链接
</el-link>
<el-link type="primary">主要链接</el-link>
<el-link type="success">成功链接</el-link>
<el-link type="warning">警告链接</el-link>
<el-link type="danger">危险链接</el-link>
<el-link type="info">信息链接</el-link>
<el-link disabled>默认链接</el-link>
<el-link type="primary" disabled>主要链接</el-link>
<el-link type="success" disabled>成功链接</el-link>
<el-link type="warning" disabled>警告链接</el-link>
<el-link type="danger" disabled>危险链接</el-link>
<el-link type="info" disabled>信息链接</el-link>
<el-link :underline="false">无下划线</el-link>
<el-link>有下划线</el-link>
<el-divider content-position="left">
头像
<a
target="_blank"
href="https://element.eleme.cn/#/zh-CN/component/avatar"
>
文档
</a>
</el-divider>
<el-avatar icon="el-icon-user-solid"></el-avatar>
<el-divider content-position="left">
页头
<a
target="_blank"
href="https://element.eleme.cn/#/zh-CN/component/page-header"
>
文档
</a>
</el-divider>
<el-page-header content="详情页面"></el-page-header>
<el-divider content-position="left">
面包屑
<a
target="_blank"
href="https://element.eleme.cn/#/zh-CN/component/breadcrumb"
>
文档
</a>
</el-divider>
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item><a href="/">活动管理</a></el-breadcrumb-item>
<el-breadcrumb-item>活动列表</el-breadcrumb-item>
<el-breadcrumb-item>活动详情</el-breadcrumb-item>
</el-breadcrumb>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: "Element",
components: {},
data() {
return {
dialogVisible: false,
};
},
created() {},
mounted() {},
methods: {},
};
</script>
<style lang="scss" scoped>
.element-container {
::v-deep {
.el-dialog__wrapper {
position: fixed;
top: 20px;
right: 20px;
bottom: 20px;
left: 20px;
}
.el-tag,
.el-button,
.el-link {
margin: 5px;
}
.el-progress {
margin: 20px;
}
}
.element-iframe {
position: absolute;
top: 55px;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 89vh;
}
}
</style>
<template>
<!-- js代码错误实时提醒测试 -->
<div>{{ chuzhixinjiayou.chuzhixinjiayou }}</div>
</template>
<script>
export default {
name: "ErrorTest",
data() {
return {};
},
};
</script>
<template>
<div class="errorLog-container">
<el-divider content-position="left">
这里会在顶部navbar上模拟一个控制台错误日志
</el-divider>
<el-button type="primary" @click="handleError">
点击模拟一个chuzhixinjiayou的错误
</el-button>
<error-test v-if="show" />
</div>
</template>
<script>
import ErrorTest from "./components/ErrorTest";
export default {
name: "ErrorLog",
components: { ErrorTest },
data() {
return { show: false };
},
methods: {
handleError() {
this.show = true;
},
},
};
</script>
<template>
<div class="form-container">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
<el-form
ref="ruleForm"
:model="ruleForm"
:rules="rules"
label-width="100px"
class="demo-ruleForm"
>
<el-form-item label="活动名称" prop="name">
<el-input v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item label="活动区域" prop="region">
<el-select v-model="ruleForm.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="即时配送" prop="delivery">
<el-switch v-model="ruleForm.delivery"></el-switch>
</el-form-item>
<el-form-item label="活动性质" prop="type">
<el-checkbox-group v-model="ruleForm.type">
<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
<el-checkbox label="地推活动" name="type"></el-checkbox>
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="特殊资源" prop="resource">
<el-radio-group v-model="ruleForm.resource">
<el-radio label="线上品牌商赞助"></el-radio>
<el-radio label="线下场地免费"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="活动形式" prop="desc">
<el-input v-model="ruleForm.desc" type="textarea"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">
立即创建
</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: "Form",
data() {
return {
ruleForm: {
name: "",
region: "",
delivery: false,
type: [],
resource: "",
desc: "",
},
rules: {
name: [
{ required: true, message: "请输入活动名称", trigger: "blur" },
{
min: 3,
max: 5,
message: "长度在 3 到 5 个字符",
trigger: "blur",
},
],
region: [
{ required: true, message: "请选择活动区域", trigger: "change" },
],
type: [
{
type: "array",
required: true,
message: "请至少选择一个活动性质",
trigger: "change",
},
],
resource: [
{ required: true, message: "请选择活动资源", trigger: "change" },
],
desc: [
{ required: true, message: "请填写活动形式", trigger: "blur" },
],
},
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert("submit!");
} else {
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
},
};
</script>
<template>
<div class="colorful-icon-container">
<el-row :gutter="20">
<el-col :span="24">
<el-divider content-position="left">
多彩图标在演示环境中使用的是cdn加速服务,开发时需存储到本地,使用方法可查看群文档,点击图标即可复制源码
</el-divider>
</el-col>
<el-col :span="24">
<el-form :inline="true" label-width="80px" @submit.native.prevent>
<el-form-item label="图标名称">
<el-input v-model="queryForm.title"></el-input>
</el-form-item>
<el-form-item label-width="0">
<el-button native-type="submit" type="primary" @click="queryData">
搜索
</el-button>
</el-form-item>
<!-- <el-form-item label-width="0">
<el-input :value="copyText" type="text"></el-input>
</el-form-item>-->
</el-form>
</el-col>
<el-col
v-for="(item, index) in queryIcon"
:key="index"
:xs="6"
:sm="8"
:md="3"
:lg="2"
:xl="2"
>
<el-card
shadow="hover"
style="cursor: pointer"
@click.native="handleCopyIcon(index, $event)"
>
<vab-colorful-icon
:icon-class="`https://cdn.jsdelivr.net/gh/chuzhixin/zx-colorful-icon@master/${item}.svg`"
/>
</el-card>
<div class="icon-text">{{ item }}</div>
</el-col>
<el-col :span="24">
<el-pagination
:background="background"
:current-page="queryForm.pageNo"
:page-size="queryForm.pageSize"
:page-sizes="[72, 144, 216, 288]"
:layout="layout"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
></el-pagination>
</el-col>
</el-row>
</div>
</template>
<script>
import { getIconList } from "@/api/colorfulIcon";
import clip from "@/utils/clipboard";
export default {
name: "ColorfulIcon",
data() {
return {
copyText: "",
layout: "total, sizes, prev, pager, next, jumper",
total: 0,
background: true,
height: 0,
selectRows: "",
elementLoadingText: "正在加载...",
queryIcon: [],
queryForm: {
pageNo: 1,
pageSize: 72,
title: "",
},
};
},
created() {
this.fetchData();
},
methods: {
handleSizeChange(val) {
this.queryForm.pageSize = val;
this.fetchData();
},
handleCurrentChange(val) {
this.queryForm.pageNo = val;
this.fetchData();
},
queryData() {
this.queryForm.pageNo = 1;
this.fetchData();
},
async fetchData() {
const { data, totalCount } = await getIconList(this.queryForm);
this.queryIcon = data;
this.allIcon = data;
this.total = totalCount;
},
handleCopyIcon(index, event) {
//const copyText = `<vab-colorful-icon icon-class="https://cdn.jsdelivr.net/gh/chuzhixin/zx-colorful-icon@master/${this.queryIcon[index]}.svg" />`;
const copyText = `<vab-colorful-icon icon-class="${this.queryIcon[index]}" />`;
this.copyText = copyText;
clip(copyText, event);
},
},
};
</script>
<style lang="scss" scoped>
.colorful-icon-container {
::v-deep {
.el-card__body {
position: relative;
display: flex;
flex-direction: column;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
svg:not(:root) {
font-size: 35px;
font-weight: bold;
color: $base-color-gray;
text-align: center;
vertical-align: middle;
pointer-events: none;
cursor: pointer;
}
.svg-external-icon {
width: 35px;
height: 35px;
}
}
}
.icon-text {
height: 30px;
margin-top: -15px;
overflow: hidden;
font-size: 12px;
line-height: 30px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
}
}
</style>
<template>
<div class="icon-container">
<el-row :gutter="20">
<el-col :span="24">
<el-divider content-position="left">点击图标即可复制源码</el-divider>
</el-col>
<el-col :span="24">
<el-form :inline="true" label-width="80px" @submit.native.prevent>
<el-form-item label="图标名称">
<el-input v-model="queryForm.title"></el-input>
</el-form-item>
<el-form-item label-width="0">
<el-button native-type="submit" type="primary" @click="queryData">
搜索
</el-button>
</el-form-item>
</el-form>
</el-col>
<el-col
v-for="(item, index) in queryIcon"
:key="index"
:xs="6"
:sm="8"
:md="3"
:lg="2"
:xl="2"
>
<el-card
shadow="hover"
style="cursor: pointer"
@click.native="handleCopyIcon(index, $event)"
>
<vab-icon :icon="['fas', item]" />
</el-card>
<div class="icon-text">{{ item }}</div>
</el-col>
<el-col :span="24">
<el-pagination
:background="background"
:current-page="queryForm.pageNo"
:page-size="queryForm.pageSize"
:page-sizes="[72, 144, 216, 288]"
:layout="layout"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
></el-pagination>
</el-col>
</el-row>
</div>
</template>
<script>
import clip from "@/utils/clipboard";
import { getIconList } from "@/api/icon";
export default {
name: "AwesomeIcon",
data() {
return {
copyText: "",
layout: "total, sizes, prev, pager, next, jumper",
total: 0,
background: true,
height: 0,
selectRows: "",
elementLoadingText: "正在加载...",
queryIcon: [],
queryForm: {
pageNo: 1,
pageSize: 72,
title: "",
},
};
},
created() {
this.fetchData();
},
methods: {
handleSizeChange(val) {
this.queryForm.pageSize = val;
this.fetchData();
},
handleCurrentChange(val) {
this.queryForm.pageNo = val;
this.fetchData();
},
queryData() {
this.queryForm.pageNo = 1;
this.fetchData();
},
async fetchData() {
const { data, totalCount } = await getIconList(this.queryForm);
this.queryIcon = data;
this.allIcon = data;
this.total = totalCount;
},
handleCopyIcon(index, event) {
const copyText = `<vab-icon :icon="['fas', '${this.queryIcon[index]}']"></vab-icon>`;
this.copyText = copyText;
clip(copyText, event);
},
},
};
</script>
<style lang="scss" scoped>
.icon-container {
::v-deep {
.el-card__body {
position: relative;
display: flex;
flex-direction: column;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
svg:not(:root).svg-inline--fa {
font-size: 35px;
font-weight: bold;
color: $base-color-gray;
text-align: center;
vertical-align: middle;
pointer-events: none;
cursor: pointer;
}
}
}
.icon-text {
height: 30px;
margin-top: -15px;
overflow: hidden;
font-size: 12px;
line-height: 30px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
}
}
</style>
<template>
<div class="colorful-icon-container">
<el-row :gutter="20">
<el-col :span="24">
<el-divider content-position="left">
小清新图标在演示环境中使用的是cdn加速服务,开发时需存储到本地,使用方法可查看群文档,点击图标即可复制源码,点击图标即可复制源码
</el-divider>
</el-col>
<el-col :span="24">
<el-form :inline="true" label-width="80px" @submit.native.prevent>
<el-form-item label="图标名称">
<el-input v-model="queryForm.title"></el-input>
</el-form-item>
<el-form-item label-width="0">
<el-button native-type="submit" type="primary" @click="queryData">
搜索
</el-button>
</el-form-item>
<!-- <el-form-item label-width="0">
<el-input :value="copyText" type="text"></el-input>
</el-form-item>-->
</el-form>
</el-col>
<el-col
v-for="(item, index) in queryIcon"
:key="index"
:xs="6"
:sm="8"
:md="3"
:lg="2"
:xl="2"
>
<el-card
shadow="hover"
style="cursor: pointer"
@click.native="handleCopyIcon(index, $event)"
>
<vab-remix-icon
:icon-class="`https://cdn.jsdelivr.net/gh/chuzhixin/zx-remixicon/src/icons/svg/${item}.svg`"
@click.stop
></vab-remix-icon>
</el-card>
<div class="icon-text">{{ item }}</div>
</el-col>
<el-col :span="24">
<el-pagination
:background="background"
:current-page="queryForm.pageNo"
:page-size="queryForm.pageSize"
:page-sizes="[72, 144, 216, 288]"
:layout="layout"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
></el-pagination>
</el-col>
</el-row>
</div>
</template>
<script>
import { getIconList } from "@/api/remixIcon";
import clip from "@/utils/clipboard";
export default {
name: "RemixIcon",
data() {
return {
copyText: "",
layout: "total, sizes, prev, pager, next, jumper",
total: 0,
background: true,
height: 0,
selectRows: "",
elementLoadingText: "正在加载...",
queryIcon: [],
queryForm: {
pageNo: 1,
pageSize: 72,
title: "",
},
};
},
created() {
this.fetchData();
},
methods: {
handleSizeChange(val) {
this.queryForm.pageSize = val;
this.fetchData();
},
handleCurrentChange(val) {
this.queryForm.pageNo = val;
this.fetchData();
},
queryData() {
this.queryForm.pageNo = 1;
this.fetchData();
},
async fetchData() {
const { data, totalCount } = await getIconList(this.queryForm);
this.queryIcon = data;
this.allIcon = data;
this.total = totalCount;
},
handleCopyIcon(index, event) {
//const copyText = `<vab-remix-icon icon-class="https://cdn.jsdelivr.net/gh/chuzhixin/zx-remixicon@master/src/icons/svg/${this.queryIcon[index]}.svg" />`;
const copyText = `<vab-remix-icon icon-class="${this.queryIcon[index]}" />`;
this.copyText = copyText;
clip(copyText, event);
},
},
};
</script>
<style lang="scss" scoped>
.colorful-icon-container {
::v-deep {
.el-card__body {
position: relative;
display: flex;
flex-direction: column;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
svg:not(:root),
.svg-external-icon {
font-size: 28px;
font-weight: bold;
color: $base-color-gray;
text-align: center;
vertical-align: middle;
pointer-events: none;
cursor: pointer;
}
}
}
.icon-text {
height: 30px;
margin-top: -15px;
overflow: hidden;
font-size: 12px;
line-height: 30px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
}
}
</style>
<template>
<div class="image-comparison-container">
<el-row :gutter="20">
<el-col
v-for="(item, index) in 24"
:key="index"
:xs="24"
:sm="24"
:md="12"
:lg="8"
:xl="8"
>
<vab-comparison
:id="'silder-' + index"
style="margin-bottom: 12px"
:width="comparison.width"
:height="comparison.height"
:src1="comparison.src1"
:src2="comparison.src2"
:start="random(20, 80)"
></vab-comparison>
</el-col>
</el-row>
</div>
</template>
<script>
import VabComparison from "@/plugins/vabComparison";
import { random } from "@/utils";
export default {
name: "ImgComparison",
components: { VabComparison },
data() {
return {
comparison: {
width: "100%",
height: "auto",
src1: require("@/assets/comparison/left.jpg"),
src2: require("@/assets/comparison/right.jpg"),
start: random(0, 100),
},
};
},
created() {},
mounted() {},
methods: {
random(m, n) {
return random(m, n).toString();
},
},
};
</script>
<template>
<div class="loading-container">
<el-divider content-position="left">传统loading</el-divider>
<el-button type="primary" @click="handleLoading()">默认效果</el-button>
<el-button type="primary" @click="handleLoading(1)">效果1</el-button>
<el-button type="primary" @click="handleLoading(2)">效果2</el-button>
<el-button type="primary" @click="handleLoading(3)">效果3</el-button>
<el-button type="primary" @click="handleLoading(4)">效果4</el-button>
<el-button type="primary" @click="handleLoading(5)">效果5</el-button>
<el-button type="primary" @click="handleLoading(6)">效果6</el-button>
<el-button type="primary" @click="handleLoading(7)">效果7</el-button>
<el-button type="primary" @click="handleLoading(8)">效果8</el-button>
<el-button type="primary" @click="handleLoading(9)">效果9</el-button>
<br />
<br />
<br />
<el-divider content-position="left">多彩loading</el-divider>
<el-button type="primary" @click="handleColorfullLoading(1)">
效果1
</el-button>
<el-button type="primary" @click="handleColorfullLoading(2)">
效果2
</el-button>
<el-button type="primary" @click="handleColorfullLoading(3)">
效果3
</el-button>
<el-button type="primary" @click="handleColorfullLoading(4)">
效果4
</el-button>
</div>
</template>
<script>
export default {
name: "Loading",
data() {
return {};
},
methods: {
handleLoading(index) {
const Loading = this.$baseLoading(index);
setTimeout(() => {
Loading.close();
}, 3000);
},
handleColorfullLoading(index) {
const Loading = this.$baseColorfullLoading(index);
setTimeout(() => {
Loading.close();
}, 3000);
},
},
};
</script>
<style lang="scss" scoped>
.loading-container {
::v-deep {
.el-button {
margin-top: 10px;
margin-right: 10px;
margin-left: 0;
}
.el-button + .el-button {
margin-right: 10px;
margin-left: 0;
}
}
}
</style>
<template>
<div class="lodash-container">
<el-row :gutter="20">
<el-col :span="24">
<el-card shadow="hover">
<el-link
type="primary"
href="https://www.lodashjs.com/"
target="_blank"
>
lodashjs官网
</el-link>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header">
<span>去除数组array中的最后一个元素</span>
</div>
<div class="lodash-content">
this.$baseLodash.initial([1, 2, 3])
<br />
// => [1, 2]
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header">
<span>返回数组 array的第一个元素</span>
</div>
<div class="lodash-content">
this.$baseLodash.head([1, 2, 3])
<br />
// => 1
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header"><span>合并数组</span></div>
<div class="lodash-content">
this.$baseLodash.concat([1],[2])
<br />
// => [1,2]
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header"><span>左切片</span></div>
<div class="lodash-content">
this.$baseLodash.drop([1, 2, 3],2切除的数量)
<br />
// => [3]
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header"><span>右切片</span></div>
<div class="lodash-content">
this.$baseLodash.dropRight([1, 2, 3],2切除的数量)
<br />
// => [1]
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header"><span>修改拼接</span></div>
<div class="lodash-content">
this.$baseLodash.join(['a', 'b', 'c'], '~');
<br />
// => 'a~b~c'
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header"><span>获取数组最后一个元素</span></div>
<div class="lodash-content">
this.$baseLodash.last(['a', 'b', 'c']);
<br />
// => 'c'
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header"><span>数组去重</span></div>
<div class="lodash-content">
this.$baseLodash.uniq(['a', 'b', 'a']);
<br />
// => ['a','b']
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header"><span>获取数组的最大值</span></div>
<div class="lodash-content">
this.$baseLodash.max([4, 2, 8, 6])
<br />
// => 8
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header"><span>获取数组的最小值</span></div>
<div class="lodash-content">
this.$baseLodash.min([4, 2, 8, 6])
<br />
// => 2
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header">
<span>四舍五入(保留任意位小数)</span>
</div>
<div class="lodash-content">
this.$baseLodash.round(4.006,2保持几位小数)
<br />
// => 4.01
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header"><span>数组内数据相加</span></div>
<div class="lodash-content">
this.$baseLodash.sum([4, 2, 8, 6])
<br />
// => 20
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header"><span>返回随机数</span></div>
<div class="lodash-content">
this.$baseLodash.random(0, 5)
<br />
// => 0到5任意数
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header"><span>返回数组内的随机数</span></div>
<div class="lodash-content">
this.$baseLodash.sample([1, 2, 3, 4])
<br />
// => 数组1到4任意数
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="6">
<el-card shadow="hover">
<div slot="header"><span>事件防抖动</span></div>
<div class="lodash-content">
this.$baseLodash.debounce(@click的事件,延迟的毫秒数)
<br />
// => 点击后多久不可以点击
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: "Lodash",
data() {
return {};
},
created() {},
mounted() {},
methods: {},
};
</script>
<style lang="scss" scoped>
.lodash-container {
text-align: left;
::v-deep {
.lodash-content {
min-height: 150px;
}
}
}
</style>
<template>
<div class="magnifier-container">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
<el-card shadow="hover">
<div slot="header"><span>放大镜1</span></div>
<vab-magnifier
url="https://picsum.photos/960/540?random=1"
type="circle"
></vab-magnifier>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
<el-card shadow="hover">
<div slot="header"><span>放大镜2</span></div>
<vab-magnifier
url="https://picsum.photos/960/540?random=2"
type="square"
></vab-magnifier>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import VabMagnifier from "@/plugins/vabMagnifier.js";
export default {
name: "Magnifier",
components: {
VabMagnifier,
},
};
</script>
<template>
<div class="map-container">
<div id="map" class="container"></div>
</div>
</template>
<script>
import axios from "axios";
import * as mapv from "mapv";
export default {
name: "Map",
components: {},
data() {
return {};
},
created() {},
mounted() {
this.$nextTick(() => {
const map = this.$baseMap();
axios
.get(
"https://cdn.jsdelivr.net/npm/mapv@2.0.12/examples/data/od-xierqi.txt"
)
.then((rs) => {
let data = [];
let timeData = [];
rs = rs.data.split("\n");
let maxLength = 0;
for (let i = 0; i < rs.length; i++) {
let item = rs[i].split(",");
let coordinates = [];
if (item.length > maxLength) {
maxLength = item.length;
}
for (let j = 0; j < item.length; j += 2) {
let x = (Number(item[j]) / 20037508.34) * 180;
let y = (Number(item[j + 1]) / 20037508.34) * 180;
y =
(180 / Math.PI) *
(2 * Math.atan(Math.exp((y * Math.PI) / 180)) - Math.PI / 2);
if (x == 0 || y == NaN) {
continue;
}
coordinates.push([x, y]);
timeData.push({
geometry: {
type: "Point",
coordinates: [x, y],
},
count: 1,
time: j,
});
}
data.push({
geometry: {
type: "LineString",
coordinates: coordinates,
},
});
}
let dataSet = new mapv.DataSet(data);
let options = {
strokeStyle: "rgba(53,57,255,0.5)",
// globalCompositeOperation: 'lighter',
shadowColor: "rgba(53,57,255,0.2)",
shadowBlur: 3,
lineWidth: 3.0,
draw: "simple",
};
let mapvLayer = new mapv.MaptalksLayer(
"mapv1",
dataSet,
options
).addTo(map);
let dataSet2 = new mapv.DataSet(timeData);
let options2 = {
fillStyle: "rgba(255, 250, 250, 0.2)",
globalCompositeOperation: "lighter",
size: 1.5,
animation: {
stepsRange: {
start: 0,
end: 100,
},
trails: 3,
duration: 5,
},
draw: "simple",
};
let mapvLayer2 = new mapv.MaptalksLayer(
"mapv2",
dataSet2,
options2
).addTo(map);
});
});
},
methods: {},
};
</script>
<style lang="scss" scoped>
.map-container {
.container {
width: 100%;
height: calc(100vh - 214px);
}
}
</style>
<template>
<div class="markdown-container markdown-body">
<el-select v-model="value" placeholder="请选择" @change="handleChange">
<el-option
v-for="(item, index) in options"
:key="index"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
<div v-html="prettierList"></div>
</div>
</template>
<script>
import marked from "marked";
import "github-markdown-css/github-markdown.css";
import { getList } from "@/api/markdown";
export default {
name: "Markdown",
data() {
return {
listLoading: true,
elementLoadingText: "正在加载...",
options: [
{
value: "0",
label: "Prettier",
},
],
value: "0",
prettierList: null,
};
},
created() {
this.fetchData();
},
mounted() {},
methods: {
handleChange(val) {
this.value = val;
this.fetchData();
},
async fetchData() {
this.listLoading = true;
switch (this.value) {
case "0":
const { data } = await getList();
this.prettierList = marked(data || "", {
renderer: new marked.Renderer(),
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: false,
smartLists: true,
smartypants: false,
});
break;
}
setTimeout(() => {
this.listLoading = false;
}, 500);
},
},
};
</script>
<template>
<div class="markdown-editor-container">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
<vab-markdown-editor
ref="mde"
v-model="value"
@show-html="handleShowHtml"
></vab-markdown-editor>
<el-button @click="handleAddText">增加文本</el-button>
<el-button @click="handleAddImg">增加图片</el-button>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
<el-card shadow="hover">
<div slot="header">
<span>markdown转换html实时演示区域</span>
</div>
<div v-html="html"></div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import VabMarkdownEditor from "@/plugins/vabMarkdownEditor";
export default {
name: "MarkdownEditor",
components: { VabMarkdownEditor },
data() {
return {
value: "# vue-admin-beautiful",
html: '<h1 id="vue-admin-beautiful">vue-admin-beautiful</h1>',
};
},
methods: {
handleAddText() {
this.$refs.mde.add("\n### 新增加的内容");
},
handleAddImg() {
this.$refs.mde.add(
"\n![](https://chu1204505056.gitee.io/byui-bookmarks/img/ewm.png)"
);
},
handleShowHtml(html) {
this.html = html;
},
},
};
</script>
<template>
<div class="more-container">
<el-divider content-position="left">
看到这里,你心动了吗?如果你心动了那就加入我们的qq群吧(972435319),谢谢你愿意尊重作者的心血,希望我们每个人都变得优秀,如果你愿意跟随作者一起学习技术,作者QQ(1204505056白嫖党勿扰)
</el-divider>
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="24" :lg="8" :xl="8">
<el-card>
<div slot="header">
开源版本
<el-button style="float: right; padding: 3px 0" type="text">
永久免费 个人/商业使用
</el-button>
</div>
<div>
<ul>
<li>永久开源免费,支持横纵布局切换</li>
<li>保留控制台以及代码中的作者信息可免费商用</li>
<li>
开源地址
<a
target="_blank"
href="https://github.com/chuzhixin/vue-admin-beautiful"
>
支持白嫖,也请给个star
</a>
</li>
<li>提供讨论群专属文档,QQ群 972435319</li>
</ul>
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="8" :xl="8">
<el-card>
<div slot="header">
VIP群
<el-button style="float: right; padding: 3px 0" type="text">
¥100
</el-button>
</div>
<div>
<ul>
<li>支持以上所有特权</li>
<li>支持四种主题</li>
<li>
vip群提供终身技术支持、专属文档及视频教程,可快速入手框架,包含打包优化,公共外框布局layout本地化及自定义教程等
</li>
<li>QQ咨询 1204505056</li>
</ul>
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="8" :xl="8">
<el-card>
<div slot="header">
开源版授权 商业用途 完全自定义版权
<el-button style="float: right; padding: 3px 0" type="text">
¥299
</el-button>
</div>
<div>
<ul>
<li>支持以上所有特权,不包含VIP群</li>
<li>
可随意变更版权,但仅限自己团队使用,禁止恶意传播,禁止二次售卖
</li>
<li>包含开源基础版授权与开源集成版授权</li>
<li>永久更新</li>
<li>提供低价外包合作机会</li>
</ul>
</div>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="8" :xl="8">
<el-card>
<div slot="header">
PRO版
<el-button style="float: right; padding: 3px 0" type="text">
¥599
</el-button>
</div>
<div>
<ul>
<li>
演示地址:
<a
target="_blank"
href="https://chu1204505056.gitee.io/vue-admin-beautiful-pro"
>
点我
</a>
</li>
<li>PRO独立版本与开源版本不同</li>
<li>无开源版限制,无版权限制,无需额外配置,拿来即用</li>
<li>免费加入vue-admin-beautifl github团队</li>
<li>提供16种布局主题搭配</li>
<li>图标使用方式大为简化</li>
<li>支持国际化语言包、中英文无缝切换(此后将支持13国语言)</li>
</ul>
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: "More",
components: {},
data() {
return { nodeEnv: process.env.NODE_ENV };
},
created() {},
mounted() {},
methods: {},
};
</script>
<style lang="scss" scoped>
.more-container {
::v-deep {
.el-card__body {
> div {
min-height: 220px;
padding: 20px;
> ul {
> li {
line-height: 30px;
}
}
> img {
display: block;
margin: 40px auto;
border: 1px solid #dedede;
}
}
}
}
}
</style>
<template>
<div class="menu1-container">
<el-alert :closable="false" title="嵌套路由 1" type="success">
<router-view />
</el-alert>
</div>
</template>
<template>
<div class="menu1-1-container">
<el-alert :closable="false" title="嵌套路由 1-1" type="success">
<router-view />
</el-alert>
</div>
</template>
<style lang="scss" scoped>
[class*="-container"] {
padding: 15px;
background: $base-color-white;
}
</style>
<template>
<div class="menu1-1-1-container">
<el-alert
:closable="false"
title="嵌套路由 1-1-1"
type="success"
></el-alert>
</div>
</template>
<style lang="scss" scoped>
[class*="-container"] {
padding: 15px;
background: $base-color-white;
}
</style>
<template>
<div class="permissions-container">
<el-divider content-position="left">
intelligence模式,前端根据permissions拦截路由(演示环境,默认使用此方案)
</el-divider>
<el-form ref="form" :model="form" :inline="true">
<el-form-item label="切换账号">
<el-radio-group v-model="form.account">
<el-radio label="admin">admin</el-radio>
<el-radio label="editor">editor</el-radio>
<el-radio label="test">test</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleChangePermission">
切换权限
</el-button>
</el-form-item>
<el-form-item label="当前账号拥有的权限">
{{ JSON.stringify(permissions) }}
</el-form-item>
</el-form>
<el-divider content-position="left">按钮级权限演示</el-divider>
<el-button v-permissions="['admin']" type="primary">
我是拥有["admin"]权限的按钮
</el-button>
<el-button v-permissions="['editor']" type="primary">
我是拥有["editor"]权限的按钮
</el-button>
<el-button v-permissions="['test']" type="primary">
我是拥有["test"]权限的按钮
</el-button>
<br />
<br />
<el-divider content-position="left">
all模式,路由以及view文件引入全部交给后端(权限复杂,且随时变更,建议使用此方案)
</el-divider>
<p>
settings.js配置authentication为all即可完全交由后端控制,mock中有后端接口示例,权限繁琐,有几十种权限的项目直接用这种,
由于演示环境是mock数据模拟,可能无法展现此功能的配置,只做如下展示,便于您的理解
</p>
<br />
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<el-table
:data="tableData"
row-key="path"
border
default-expand-all
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column
show-overflow-tooltip
prop="name"
label="name"
></el-table-column>
<el-table-column
show-overflow-tooltip
prop="path"
label="path"
></el-table-column>
<el-table-column
show-overflow-tooltip
prop="component"
label="component"
></el-table-column>
<el-table-column
show-overflow-tooltip
prop="redirect"
label="redirect"
></el-table-column>
<el-table-column
show-overflow-tooltip
prop="meta.title"
label="标题"
></el-table-column>
<el-table-column show-overflow-tooltip label="图标">
<template slot-scope="scope">
<span v-if="scope.row.meta">
<vab-icon
v-if="scope.row.meta.icon"
:icon="['fas', scope.row.meta.icon]"
></vab-icon>
</span>
</template>
</el-table-column>
<el-table-column show-overflow-tooltip label="是否固定">
<template slot-scope="scope">
<span v-if="scope.row.meta">
{{ scope.row.meta.affix }}
</span>
</template>
</el-table-column>
<el-table-column show-overflow-tooltip label="是否无缓存">
<template slot-scope="scope">
<span v-if="scope.row.meta">
{{ scope.row.meta.noKeepAlive }}
</span>
</template>
</el-table-column>
<el-table-column show-overflow-tooltip label="badge">
<template slot-scope="scope">
<span v-if="scope.row.meta">
{{ scope.row.meta.badge }}
</span>
</template>
</el-table-column>
</el-table>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<json-editor :value="res"></json-editor>
</el-col>
</el-row>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import { tokenTableName } from "@/config/settings";
import { getRouterList } from "@/api/router";
import JsonEditor from "@/components/JsonEditor";
export default {
name: "Permissions",
components: {
JsonEditor,
},
data() {
return {
form: {
account: "",
},
tableData: [],
res: [],
};
},
computed: {
...mapGetters({
username: "user/username",
permissions: "user/permissions",
}),
},
created() {
this.fetchData();
},
mounted() {
this.form.account = this.username;
},
methods: {
handleChangePermission() {
localStorage.setItem(
tokenTableName,
`${this.form.account}-accessToken`
);
location.reload();
},
async fetchData() {
const res = await getRouterList();
this.tableData = res.data;
this.res = res;
},
},
};
</script>
<template>
<div class="player-container">
<el-divider content-position="left">
视频地址采用cdn加速服务,开发时需部署到到本地,使用方法可查看群文档
</el-divider>
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
<el-card shadow="hover">
<div slot="header">播放传统MP4</div>
<vab-player-mp4 :config="config1" @player="Player1 = $event" />
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
<el-card shadow="hover">
<div slot="header">播放m3u8,且不暴露视频地址</div>
<vab-player-hls
:config="config2"
@player="Player2 = $event"
></vab-player-hls>
</el-card>
</el-col>
<!--<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
<el-card shadow="hover">
<div slot="header">播放flv,且不暴露视频地址</div>
<vab-player-flv
:config="config3"
@player="Player3 = $event"
></vab-player-flv>
</el-card>
</el-col>-->
</el-row>
</div>
</template>
<script>
import { VabPlayerMp4, VabPlayerHls } from "@/plugins/vabPlayer.js";
export default {
name: "Player",
components: {
VabPlayerMp4,
VabPlayerHls,
},
data() {
return {
config1: {
id: "mse1",
url: "https://cdn.jsdelivr.net/gh/chuzhixin/videos@master/video.mp4",
volume: 1,
autoplay: false,
},
Player1: null,
config2: {
id: "mse2",
url: "https://cdn.jsdelivr.net/gh/chuzhixin/videos@master/video.m3u8",
volume: 1,
autoplay: false,
},
Player2: null,
config3: {
id: "mse3",
url: "https://cdn.jsdelivr.net/gh/chuzhixin/videos@master/video.flv",
volume: 1,
autoplay: false,
},
Player3: null,
};
},
created() {},
mounted() {},
methods: {},
};
</script>
<template>
<div class="qr-code-container">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
<el-card shadow="hover">
<div slot="header"><span>二维码示例</span></div>
<a target="_blank" :href="url">
<vab-qr-code :image-path="imagePath" :url="url"></vab-qr-code>
</a>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import VabQrCode from "@/components/VabQrCode";
export default {
name: "QrCode",
components: {
VabQrCode,
},
data() {
return {
url: "https://www.baidu.com",
imagePath: require("@/assets/qr_logo/lqr_logo.png"),
};
},
created() {},
mounted() {},
methods: {},
};
</script>
<style lang="scss" scoped>
.qr-code-container {
::v-deep {
.el-card__body {
display: flex;
align-content: center;
justify-content: center;
}
}
}
</style>
<template>
<div class="small-components-container">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
<el-divider content-position="left">小组件</el-divider>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
<el-card shadow="hover">
<div slot="header">
<span>snow</span>
</div>
<vab-snow></vab-snow>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
<el-card shadow="hover">
<div slot="header">
<span>profile</span>
<el-button
style="float: right; padding: 3px 0"
type="text"
@click="handleProfile"
>
重载
</el-button>
</div>
<vab-profile
v-if="profileShow"
avatar="https://picsum.photos/80/80?random=2"
user-name="chuzhixin"
></vab-profile>
</el-card>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
<el-card shadow="hover">
<div slot="header">
<span>charge</span>
</div>
<vab-charge :start-val="startVal" :end-val="endVal"></vab-charge>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import VabSnow from "@/components/VabSnow";
import VabProfile from "@/components/VabProfile";
import VabCharge from "@/components/VabCharge";
export default {
name: "Sticky",
components: {
VabSnow,
VabProfile,
VabCharge,
},
data() {
return {
profileShow: true,
faultTextShow: true,
solidTextShow: true,
startVal: 0,
endVal: 20,
timeInterval: null,
};
},
mounted() {
this.handleProfile();
this.handleSolidText();
this.timeInterval = setInterval(() => {
if (this.endVal < 100) {
this.startVal = this.endVal;
this.endVal++;
}
}, 5000);
},
beforeDestroy() {
if (this.clearInterval) {
clearInterval(this.timeInterval);
}
},
methods: {
handleProfile() {
this.profileShow = false;
setTimeout(() => {
this.profileShow = true;
});
},
handleSolidText() {
this.solidTextShow = false;
setTimeout(() => {
this.solidTextShow = true;
});
},
},
};
</script>
<style lang="scss" scoped>
.small-components-container {
::v-deep {
.el-card__body {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
height: 430px;
}
}
}
</style>
<template>
<div class="sticky-container">
<vab-sticky :sticky-top="100">
<el-alert title="我会吸附" type="success" :closable="false"></el-alert>
</vab-sticky>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<vab-sticky :sticky-top="150">
<el-alert title="我会吸附" type="success" :closable="false"></el-alert>
</vab-sticky>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<vab-sticky :sticky-top="200">
<el-alert title="我会吸附" type="success" :closable="false"></el-alert>
</vab-sticky>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<vab-sticky :sticky-top="250">
<el-alert title="我会吸附" type="success" :closable="false"></el-alert>
</vab-sticky>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<vab-sticky :sticky-top="300">
<el-alert title="我会吸附" type="success" :closable="false"></el-alert>
</vab-sticky>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<vab-sticky :sticky-top="350">
<el-alert title="我会吸附" type="success" :closable="false"></el-alert>
</vab-sticky>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<vab-sticky :sticky-top="400">
<el-alert title="我会吸附" type="success" :closable="false"></el-alert>
</vab-sticky>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<vab-sticky :sticky-top="450">
<el-alert title="我会吸附" type="success" :closable="false"></el-alert>
</vab-sticky>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<vab-sticky :sticky-top="500">
<el-alert title="我会吸附" type="success" :closable="false"></el-alert>
</vab-sticky>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<vab-sticky :sticky-top="550">
<el-alert title="我会吸附" type="success" :closable="false"></el-alert>
</vab-sticky>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<vab-sticky :sticky-top="600">
<el-alert title="我会吸附" type="success" :closable="false"></el-alert>
</vab-sticky>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<vab-sticky :sticky-top="650">
<el-alert title="我会吸附" type="success" :closable="false"></el-alert>
</vab-sticky>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
<div>sticky</div>
</div>
</template>
<script>
import VabSticky from "@/components/VabSticky";
export default {
name: "Sticky",
components: { VabSticky },
data() {
return {
time: "",
url: "",
platforms: ["a-platform"],
platformsOptions: [
{ key: "a-platform", name: "platformA" },
{ key: "b-platform", name: "platformB" },
{ key: "c-platform", name: "platformC" },
],
pickerOptions: {
disabledDate(time) {
return time.getTime() > Date.now();
},
},
};
},
};
</script>
<style lang="scss" scoped>
.sticky-container {
div {
height: 40px;
line-height: 40px;
}
}
</style>
<template>
<el-dialog
:title="title"
:visible.sync="dialogFormVisible"
width="500px"
@close="close"
>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="标题" prop="title">
<el-input v-model.trim="form.title" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="作者" prop="author">
<el-input v-model.trim="form.author" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="close">取 消</el-button>
<el-button type="primary" @click="save">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
import { doEdit } from "@/api/table";
export default {
name: "TableEdit",
data() {
return {
form: {
title: "",
author: "",
},
rules: {
title: [{ required: true, trigger: "blur", message: "请输入标题" }],
author: [{ required: true, trigger: "blur", message: "请输入作者" }],
},
title: "",
dialogFormVisible: false,
};
},
created() {},
methods: {
showEdit(row) {
if (!row) {
this.title = "添加";
} else {
this.title = "编辑";
this.form = Object.assign({}, row);
}
this.dialogFormVisible = true;
},
close() {
this.$refs["form"].resetFields();
this.form = this.$options.data().form;
this.dialogFormVisible = false;
this.$emit("fetchData");
},
save() {
this.$refs["form"].validate(async (valid) => {
if (valid) {
const { msg } = await doEdit(this.form);
this.$baseMessage(msg, "success");
this.$refs["form"].resetFields();
this.dialogFormVisible = false;
this.$emit("fetchData");
this.form = this.$options.data().form;
} else {
return false;
}
});
},
},
};
</script>
<template>
<div class="table-container">
<vab-query-form>
<vab-query-form-left-panel>
<el-button icon="el-icon-plus" type="primary" @click="handleAdd">
添加
</el-button>
<el-button icon="el-icon-delete" type="danger" @click="handleDelete">
删除
</el-button>
<el-button type="primary" @click="testMessage">baseMessage</el-button>
<el-button type="primary" @click="testALert">baseAlert</el-button>
<el-button type="primary" @click="testConfirm">baseConfirm</el-button>
<el-button type="primary" @click="testNotify">baseNotify</el-button>
</vab-query-form-left-panel>
<vab-query-form-right-panel>
<el-form
ref="form"
:model="queryForm"
:inline="true"
@submit.native.prevent
>
<el-form-item>
<el-input v-model="queryForm.title" placeholder="标题" />
</el-form-item>
<el-form-item>
<el-button
icon="el-icon-search"
type="primary"
native-type="submit"
@click="handleQuery"
>
查询
</el-button>
</el-form-item>
</el-form>
</vab-query-form-right-panel>
</vab-query-form>
<el-table
ref="tableSort"
v-loading="listLoading"
:data="list"
:element-loading-text="elementLoadingText"
@selection-change="setSelectRows"
@sort-change="tableSortChange"
>
<el-table-column
show-overflow-tooltip
type="selection"
width="55"
></el-table-column>
<el-table-column show-overflow-tooltip label="序号" width="95">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column
show-overflow-tooltip
prop="title"
label="标题"
></el-table-column>
<el-table-column
show-overflow-tooltip
label="作者"
prop="author"
></el-table-column>
<el-table-column show-overflow-tooltip label="头像">
<template slot-scope="scope">
<el-image
v-if="imgShow"
:preview-src-list="imageList"
:src="scope.row.img"
></el-image>
</template>
</el-table-column>
<el-table-column
show-overflow-tooltip
label="点击量"
prop="pageViews"
sortable
></el-table-column>
<el-table-column show-overflow-tooltip label="状态">
<template slot-scope="scope">
<el-tooltip
:content="scope.row.status"
class="item"
effect="dark"
placement="top-start"
>
<el-tag :type="scope.row.status | statusFilter">
{{ scope.row.status }}
</el-tag>
</el-tooltip>
</template>
</el-table-column>
<el-table-column
show-overflow-tooltip
label="时间"
prop="datetime"
width="200"
></el-table-column>
<el-table-column
show-overflow-tooltip
label="操作"
width="180px"
fixed="right"
>
<template slot-scope="scope">
<el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
<el-button type="text" @click="handleDelete(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
:background="background"
:current-page="queryForm.pageNo"
:layout="layout"
:page-size="queryForm.pageSize"
:total="total"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
></el-pagination>
<table-edit ref="edit"></table-edit>
</div>
</template>
<script>
import { getList, doDelete } from "@/api/table";
import TableEdit from "./components/TableEdit";
export default {
name: "ComprehensiveTable",
components: {
TableEdit,
},
filters: {
statusFilter(status) {
const statusMap = {
published: "success",
draft: "gray",
deleted: "danger",
};
return statusMap[status];
},
},
data() {
return {
imgShow: true,
list: [],
imageList: [],
listLoading: true,
layout: "total, sizes, prev, pager, next, jumper",
total: 0,
background: true,
selectRows: "",
elementLoadingText: "正在加载...",
queryForm: {
pageNo: 1,
pageSize: 20,
title: "",
},
};
},
created() {
this.fetchData();
},
beforeDestroy() {},
mounted() {},
methods: {
tableSortChange() {
const imageList = [];
this.$refs.tableSort.tableData.forEach((item, index) => {
imageList.push(item.img);
});
this.imageList = imageList;
},
setSelectRows(val) {
this.selectRows = val;
},
handleAdd() {
this.$refs["edit"].showEdit();
},
handleEdit(row) {
this.$refs["edit"].showEdit(row);
},
handleDelete(row) {
if (row.id) {
this.$baseConfirm("你确定要删除当前项吗", null, async () => {
const { msg } = await doDelete({ ids: row.id });
this.$baseMessage(msg, "success");
this.fetchData();
});
} else {
if (this.selectRows.length > 0) {
const ids = this.selectRows.map((item) => item.id).join();
this.$baseConfirm("你确定要删除选中项吗", null, async () => {
const { msg } = await doDelete({ ids: ids });
this.$baseMessage(msg, "success");
this.fetchData();
});
} else {
this.$baseMessage("未选中任何行", "error");
return false;
}
}
},
handleSizeChange(val) {
this.queryForm.pageSize = val;
this.fetchData();
},
handleCurrentChange(val) {
this.queryForm.pageNo = val;
this.fetchData();
},
handleQuery() {
this.queryForm.pageNo = 1;
this.fetchData();
},
async fetchData() {
this.listLoading = true;
const { data, totalCount } = await getList(this.queryForm);
this.list = data;
const imageList = [];
data.forEach((item, index) => {
imageList.push(item.img);
});
this.imageList = imageList;
this.total = totalCount;
setTimeout(() => {
this.listLoading = false;
}, 500);
},
testMessage() {
this.$baseMessage("test1", "success");
},
testALert() {
this.$baseAlert("11");
this.$baseAlert("11", "自定义标题", () => {
/* 可以写回调; */
});
this.$baseAlert("11", null, () => {
/* 可以写回调; */
});
},
testConfirm() {
this.$baseConfirm(
"你确定要执行该操作?",
null,
() => {
/* 可以写回调; */
},
() => {
/* 可以写回调; */
}
);
},
testNotify() {
this.$baseNotify("测试消息提示", "test", "success", "bottom-right");
},
},
};
</script>
<template>
<div class="app-container">
<el-table
v-loading="listLoading"
:data="list"
:element-loading-text="elementLoadingText"
>
<el-table-column
show-overflow-tooltip
type="selection"
width="55"
></el-table-column>
<el-table-column show-overflow-tooltip label="序号" width="95">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column show-overflow-tooltip min-width="300px" label="标题">
<template slot-scope="{ row }">
<template v-if="row.edit">
<el-input v-model="row.title" style="width: 300px" />
<el-button
class="cancel-btn"
type="warning"
@click="cancelEdit(row)"
>
取消
</el-button>
</template>
<span v-else>{{ row.title }}</span>
</template>
</el-table-column>
<el-table-column
show-overflow-tooltip
label="作者"
prop="author"
></el-table-column>
<el-table-column
show-overflow-tooltip
align="center"
label="操作"
width="200"
>
<template slot-scope="{ row }">
<el-button
v-if="row.edit"
type="success"
size="small"
@click="confirmEdit(row)"
>
保存
</el-button>
<el-button
v-else
type="primary"
size="small"
icon="el-icon-edit"
@click="row.edit = !row.edit"
>
编辑
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { getList } from "@/api/table";
export default {
name: "InlineEditTable",
data() {
return {
list: null,
listLoading: true,
elementLoadingText: "正在加载...",
queryForm: {
pageNo: 1,
pageSize: 20,
title: "",
},
};
},
created() {
this.getList();
},
methods: {
async getList() {
this.listLoading = true;
const { data } = await getList(this.queryForm);
this.list = data.map((v) => {
this.$set(v, "edit", false);
v.originalTitle = v.title;
return v;
});
this.listLoading = false;
},
cancelEdit(row) {
row.title = row.originalTitle;
row.edit = false;
},
confirmEdit(row) {
row.edit = false;
row.originalTitle = row.title;
},
},
};
</script>
<template>
<div class="tree-container">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="24" :lg="6" :xl="6">
<el-divider content-position="left">常规树</el-divider>
<el-input v-model="filterText" placeholder="输入关键字过滤" />
<el-tree
ref="demoTree"
:data="data2"
:default-checked-keys="defaultCheckedKeys"
:default-expanded-keys="defaultExpendedKeys"
:expand-on-click-node="false"
:filter-node-method="filterNode"
:highlight-current="true"
:props="defaultProps"
class="vab-filter-tree"
node-key="id"
show-checkbox
@check="checkNode"
@node-click="nodeClick"
@node-collapse="nodeCollapse"
@node-expand="nodeExpand"
>
<span slot-scope="{ node, data }" class="vab-custom-tree-node">
<span class="vab-tree-item">
<i v-if="node.data.rank == 4" class="el-icon-s-custom"></i>
{{ node.label }}
</span>
<span class="vab-tree-options">
<a
v-if="node.data.rank !== 4"
class="vab-tree-btn"
title="添加"
@click="() => append(node, data, 0)"
>
<i class="el-icon-plus"></i>
</a>
<a
class="vab-tree-btn"
title="编辑"
@click="() => edit(node, data, 1)"
>
<i class="el-icon-edit"></i>
</a>
<a
v-if="node.data.rank !== 1"
class="vab-tree-btn"
title="刪除"
@click="() => remove(node, data)"
>
<i class="el-icon-delete"></i>
</a>
</span>
</span>
</el-tree>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="6" :xl="6">
<el-divider content-position="left">懒加载树</el-divider>
<el-input
v-model.lazy="keyW"
:value="keyW"
class="input-with-select"
placeholder="请输入内容"
@keyup.enter.native="showTreeList"
></el-input>
<div v-show="isShow" class="blur-tree">
<el-tree
ref="treeFilter"
:data="filterDevLlist"
:expand-on-click-node="false"
:props="defaultProps"
class="vab-filter-tree"
default-expand-all
highlight-current
node-key="indexCode"
@node-click="nodeClick"
>
<span slot-scope="{ node }" class="vab-custom-tree-node">
<span class="vab-tree-item">
<i v-if="node.data.rank == 4" class="el-icon-s-custom"></i>
{{ node.label }}
</span>
<span class="vab-tree-options">
<a
v-if="node.data.rank !== 4"
class="vab-tree-btn"
title="添加"
>
<i class="el-icon-plus"></i>
</a>
<a class="vab-tree-btn" title="编辑">
<i class="el-icon-edit"></i>
</a>
<a
v-if="node.data.rank !== 1"
class="vab-tree-btn"
title="刪除"
>
<i class="el-icon-delete"></i>
</a>
</span>
</span>
</el-tree>
</div>
<div v-show="!isShow" class="el-tree-wrap">
<el-tree
ref="tree"
v-loading="loading"
:expand-on-click-node="false"
:load="loadNode"
:props="defaultProps"
class="vab-filter-tree"
highlight-current
lazy
node-key="indexCode"
@node-click="nodeClick"
>
<span slot-scope="{ node }" class="vab-custom-tree-node">
<span class="vab-tree-item">
<i v-if="node.data.rank == 4" class="el-icon-s-custom"></i>
{{ node.label }}
</span>
<span class="vab-tree-options">
<!-- <a v-if="node.data.rank !== 4" class="vab-tree-btn" title="添加""><i class="el-icon-plus"></i></a> -->
<a class="vab-tree-btn" title="编辑">
<i class="el-icon-edit"></i>
</a>
<a
v-if="node.data.rank !== 1"
class="vab-tree-btn"
title="刪除"
>
<i class="el-icon-delete"></i>
</a>
</span>
</span>
</el-tree>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="6" :xl="6">
<el-divider content-position="left">单选树</el-divider>
<el-select
ref="singleTree"
v-model="singleSelectTreeVal"
class="vab-tree-select"
clearable
popper-class="select-tree-popper"
value-key="id"
@clear="selectTreeClearHandle('single')"
>
<el-option :value="singleSelectTreeKey">
<el-tree
id="singleSelectTree"
ref="singleSelectTree"
:current-node-key="singleSelectTreeKey"
:data="selectTreeData"
:default-expanded-keys="selectTreeDefaultSelectedKeys"
:highlight-current="true"
:props="selectTreeDefaultProps"
node-key="id"
@node-click="selectTreeNodeClick"
>
<span slot-scope="{ node }" class="vab-custom-tree-node">
<span class="vab-tree-item">{{ node.label }}</span>
</span>
</el-tree>
</el-option>
</el-select>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="6" :xl="6">
<el-divider content-position="left">多选树</el-divider>
<el-select
v-model="multipleSelectTreeVal"
class="vab-tree-select"
clearable
collapse-tags
multiple
popper-class="select-tree-popper"
@change="changeMultipleSelectTreeHandle"
@clear="selectTreeClearHandle('multiple')"
@remove-tag="removeSelectTreeTag"
>
<el-option :value="multipleSelectTreeKey">
<el-tree
id="multipleSelectTree"
ref="multipleSelectTree"
:current-node-key="multipleSelectTreeKey"
:data="selectTreeData"
:default-checked-keys="selectTreeDefaultSelectedKeys"
:default-expanded-keys="selectTreeDefaultSelectedKeys"
:highlight-current="true"
:props="selectTreeDefaultProps"
node-key="id"
show-checkbox
@check="multipleSelectTreeCheckNode"
></el-tree>
</el-option>
</el-select>
</el-col>
</el-row>
<!--添加/编辑节点弹框-------------------start-->
<el-dialog
:title="dialogTitle"
:visible.sync="treeDialogVisible"
class="tree-operate-dialog"
width="400px"
@close="treeDialogVisible = false"
>
<el-form ref="treeForm" :model="treeForm">
<el-form-item label="节点名称" required>
<el-input v-model="treeForm.name"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="treeDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="saveTree">确 定</el-button>
</div>
</el-dialog>
<!--添加/编辑节点弹框-------------------end-->
</div>
</template>
<script>
import { getTreeList } from "@/api/tree";
export default {
name: "Tree",
data() {
return {
dialogTitle: "添加节点",
treeFlag: 0,
treeDialogVisible: false,
treeForm: {
id: "",
name: "",
},
checkNodeKeys: [],
filterText: "",
data2: [],
defaultProps: {
children: "children",
label: "name",
},
defaultExpendedKeys: [],
defaultCheckedKeys: [],
loading: true,
keyW: "",
filterDevLlist: [],
isShow: false,
updateTree: true,
/* 单选树-多选树---------开始 */
selectLevel: 4, // 树可选叶子level等级
singleSelectTreeVal: "", //单选树默认label值
singleSelectTreeKey: "", //单选树默认key值
selectTreeData: [], //单选树的值
selectTreeDefaultSelectedKeys: [], //单选树默认展开的key值数组
selectTreeDefaultProps: {
children: "children",
label: "name",
},
multipleSelectTreeVal: [], //多选树默认label值
multipleSelectTreeKey: "", //多选树默认key值
/* 单选树-多选树---------结束 */
};
},
watch: {
filterText(val) {
this.$refs.demoTree.filter(val);
},
},
mounted() {
this.$nextTick(() => {
this.getTreeListFuc(1);
this.setCheckedKeys();
// 初始化单选树
this.initSingleTree("single");
// 初始化多选树
this.initSingleTree("multiple");
});
},
methods: {
// 树level小于n级展开方法
openTree(treeData, n) {
const each = (data) => {
data.forEach((e) => {
if (e.rank <= n) {
this.defaultExpendedKeys.push(e.id);
}
if (e.children.length > 0) {
each(e.children);
}
});
};
each(treeData);
},
// 获取tree数据
async getTreeListFuc(flag) {
const { data } = await getTreeList();
this.data2 = data;
if (flag) {
this.openTree(this.data2, 2);
}
},
// 节点过滤操作
filterNode(value, data) {
if (!value) return true;
return data.name.indexOf(value) !== -1;
},
// 添加节点操作
append(node, data, flag) {
this.treeFlag = flag;
this.dialogTitle = "添加节点";
this.treeForm = {
id: "",
name: "",
};
this.treeDialogVisible = true;
},
// 编辑节点操作
edit(node, data, flag) {
this.treeFlag = flag;
this.dialogTitle = "编辑节点";
this.treeForm = {
id: data.id,
name: data.name,
};
this.treeDialogVisible = true;
},
// 删除节点操作
remove(node, data) {
this.$baseConfirm("你确定要删除该节点?", null, async () => {
const { msg } = getTreeList();
this.$baseMessage(msg, "success");
this.getTreeListFuc(0);
});
},
// 保存添加和编辑
saveTree() {
this.$refs.treeForm.validate(async (valid) => {
if (valid) {
const { msg } = await getTreeList();
this.$baseMessage(msg, "success");
this.treeDialogVisible = false;
this.getTreeListFuc(0);
}
});
},
// 设置节点选中
setCheckedKeys() {
this.$refs.demoTree.setCheckedKeys([1]);
},
// 点击叶子节点
nodeClick(data, node, el) {},
// 节点选中操作
checkNode(data, node, el) {
this.checkNodeKeys = node.checkedKeys;
},
// 节点展开操作
nodeExpand(data, node, el) {
this.defaultExpendedKeys.push(data.id);
},
// 节点关闭操作
nodeCollapse(data, node, el) {
this.defaultExpendedKeys.splice(
this.defaultExpendedKeys.findIndex((item) => item.id === data.id),
1
);
},
async loadNode(node, resolve) {
if (node.level === 0) {
const { data } = await getTreeList();
this.loading = false;
return resolve(data);
} else {
const { data } = await getTreeList();
return resolve(res.data);
}
},
//懒加载树输入框筛选方法
async showTreeList(value) {
if (typeof value === "string") {
this.keyW = value.trim();
}
if (this.keyW.length !== 0) {
// 请求后台返回查询结果
let treeOption = {};
treeOption = {
keyWord: this.keyW,
};
const { data } = await getTreeList();
this.filterDevLlist = data;
this.isShow = true;
} else {
this.isShow = false;
}
},
/* 单选/多选树方法-------------------开始 */
// 初始化单选树的值
async initSingleTree(treeType) {
const { data } = await getTreeList();
this.selectTreeData = data;
this.$nextTick(() => {
this.selectTreeDefaultSelectedKeys = this.singleSelectTreeKey.split(
","
); // 设置默认展开
if (treeType == "single") {
//单选树
this.$refs.singleSelectTree.setCurrentKey(this.singleSelectTreeKey); // 设置默认选中
} else {
// 多选树
this.$refs.multipleSelectTree.setCheckedKeys(
this.selectTreeDefaultSelectedKeys
);
}
});
},
// 清除单选树选中
selectTreeClearHandle(type) {
this.selectTreeDefaultSelectedKeys = [];
this.clearSelected();
if (type == "single") {
this.singleSelectTreeVal = "";
this.singleSelectTreeKey = "";
this.$refs.singleSelectTree.setCurrentKey(""); // 设置默认选中
} else {
this.multipleSelectTreeVal = [];
this.multipleSelectTreeKey = "";
this.$refs.multipleSelectTree.setCheckedKeys([]);
}
},
/* 清空选中样式 */
clearSelected() {
const allNode = document.querySelectorAll(
"#singleSelectTree .el-tree-node"
);
allNode.forEach((element) => element.classList.remove("is-current"));
},
// select多选时移除某项操作
removeSelectTreeTag(val) {
const stack = JSON.parse(JSON.stringify(this.selectTreeData));
while (stack.length) {
const curr = stack.shift();
if (curr.name == val) {
return this.$refs.multipleSelectTree.setChecked(curr.id, false);
}
if (curr.children && curr.children.length) {
stack.unshift(...curr.children);
}
}
},
changeMultipleSelectTreeHandle(val) {},
// 点击叶子节点
selectTreeNodeClick(data, node, el) {
if (data.rank >= this.selectLevel) {
this.singleSelectTreeVal = data.name;
this.singleSelectTreeKey = data.id;
this.$refs.singleTree.blur();
}
},
// 节点选中操作
multipleSelectTreeCheckNode(data, node, el) {
const checkedNodes = this.$refs.multipleSelectTree.getCheckedNodes();
const keyArr = [];
const valueArr = [];
checkedNodes.forEach((item) => {
if (item.rank >= this.selectLevel) {
keyArr.push(item.id);
valueArr.push(item.name);
}
});
this.multipleSelectTreeVal = valueArr;
this.multipleSelectTreeKey = keyArr.join(",");
},
/* 单选/多选树方法-------------------结束 */
},
};
</script>
<template>
<div class="upload-container">
<el-divider content-position="left">演示环境可能无法模拟上传</el-divider>
<vab-upload
ref="vabUpload"
url="/upload"
name="file"
:limit="50"
:size="2"
></vab-upload>
<el-button type="primary" @click="handleShow({ key: 'value' })">
模拟上传
</el-button>
</div>
</template>
<script>
import VabUpload from "@/components/VabUpload";
export default {
name: "Upload",
components: {
VabUpload,
},
data() {
return {};
},
methods: {
handleShow(data) {
this.$refs["vabUpload"].handleShow(data);
},
},
};
</script>
<template>
<div class="verify-container">
<vab-verify
ref="slideDiv"
:w="350"
:slider-text="text"
:h="175"
@success="handleSuccess"
@fail="handleError"
></vab-verify>
</div>
</template>
<script>
import VabVerify from "@/plugins/vabVerify";
export default {
name: "Verify",
components: { VabVerify },
data() {
return {
text: "向右滑动",
};
},
created() {},
mounted() {},
methods: {
handleSuccess() {
this.$baseMessage("校验成功", "success");
},
handleError() {
this.$baseMessage("校验失败", "error");
},
},
};
</script>
<template>
<div class="webSocket-container">
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
<el-alert type="success" :closable="false">
webSocket连接{{ status }}
</el-alert>
<br />
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="地址">
<el-input v-model="url" disabled></el-input>
</el-form-item>
<el-form-item label="消息" prop="message">
<el-input v-model="form.message"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submit">发送消息</el-button>
</el-form-item>
<el-form-item label="返回信息汇总">
{{ data }}
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: "WebSocket",
components: {},
data() {
return {
url: "ws://123.207.136.134:9010/ajaxchattest",
webSocket: null,
data: [],
status: "",
form: { message: null },
rules: {
message: [{ required: true, message: "请输入消息", trigger: "blur" }],
},
};
},
created() {
this.init();
},
destroyed() {
this.webSocket.close();
},
methods: {
submit() {
this.$refs["form"].validate((valid) => {
if (valid) {
this.send(this.form.message);
} else {
return false;
}
});
},
init() {
const wsuri = this.url;
this.webSocket = new WebSocket(wsuri);
this.webSocket.onmessage = this.onmessage;
this.webSocket.onopen = this.onopen;
this.webSocket.onerror = this.onerror;
this.webSocket.onclose = this.onclose;
},
onopen() {
this.status = "成功";
},
onerror() {
this.status = "失败";
this.initWebSocket();
},
onmessage({ data }) {
//截掉测试webSocket地址广告
this.data.push(data.substring(0, data.length - 66));
},
send(Data) {
this.webSocket.send(Data);
},
onclose(e) {
this.status = "断开";
},
},
};
</script>
plugins:
- removeAttrs:
attrs:
- "fill-rule"
const path = require("path");
const {
publicPath,
assetsDir,
outputDir,
lintOnSave,
transpileDependencies,
title,
abbreviation,
devPort,
providePlugin,
build7z,
donation,
} = require("./src/config/settings");
const {
webpackBarName,
webpackBanner,
donationConsole,
} = require("zx-layouts");
if (donation) donationConsole();
const { version, author } = require("./package.json");
const Webpack = require("webpack");
const WebpackBar = require("webpackbar");
const FileManagerPlugin = require("filemanager-webpack-plugin");
const dayjs = require("dayjs");
const date = dayjs().format("YYYY_M_D");
const time = dayjs().format("YYYY-M-D HH:mm:ss");
const CompressionWebpackPlugin = require("compression-webpack-plugin");
const productionGzipExtensions = ["html", "js", "css", "svg"];
process.env.VUE_APP_TITLE = title || "vue-admin-beautiful";
process.env.VUE_APP_AUTHOR = author || "chuzhixin 1204505056@qq.com";
process.env.VUE_APP_UPDATE_TIME = time;
process.env.VUE_APP_VERSION = version;
const resolve = (dir) => {
return path.join(__dirname, dir);
};
const mockServer = () => {
if (process.env.NODE_ENV === "development") {
return require("./mock/mockServer.js");
} else {
return "";
}
};
module.exports = {
publicPath,
assetsDir,
outputDir,
lintOnSave,
transpileDependencies,
devServer: {
hot: true,
port: devPort,
open: true,
noInfo: false,
overlay: {
warnings: true,
errors: true,
},
after: mockServer(),
},
configureWebpack() {
return {
resolve: {
alias: {
"@": resolve("src"),
},
},
plugins: [
new Webpack.ProvidePlugin(providePlugin),
new WebpackBar({
name: webpackBarName,
}),
],
};
},
chainWebpack(config) {
/* config.plugins.delete("preload");
config.plugins.delete("prefetch"); */
config.module
.rule("svg")
.exclude.add(resolve("src/remixIcon"))
.add(resolve("src/colorfulIcon"))
.end();
config.module
.rule("remixIcon")
.test(/\.svg$/)
.include.add(resolve("src/remixIcon"))
.end()
.use("svg-sprite-loader")
.loader("svg-sprite-loader")
.options({ symbolId: "remix-icon-[name]" })
.end();
config.module
.rule("colorfulIcon")
.test(/\.svg$/)
.include.add(resolve("src/colorfulIcon"))
.end()
.use("svg-sprite-loader")
.loader("svg-sprite-loader")
.options({ symbolId: "colorful-icon-[name]" })
.end();
config.when(process.env.NODE_ENV === "development", (config) => {
config.devtool("source-map");
});
config.when(process.env.NODE_ENV !== "development", (config) => {
config.performance.set("hints", false);
config.devtool("none");
config.optimization.splitChunks({
chunks: "all",
cacheGroups: {
libs: {
name: "chunk-libs",
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: "initial",
},
elementUI: {
name: "chunk-elementUI",
priority: 20,
test: /[\\/]node_modules[\\/]_?element-ui(.*)/,
},
fortawesome: {
name: "chunk-fortawesome",
priority: 20,
test: /[\\/]node_modules[\\/]_?@fortawesome(.*)/,
},
commons: {
name: "chunk-commons",
test: resolve("src/components"),
minChunks: 3,
priority: 5,
reuseExistingChunk: true,
},
},
});
config
.plugin("banner")
.use(Webpack.BannerPlugin, [`${webpackBanner}${time}`])
.end();
config
.plugin("compression")
.use(CompressionWebpackPlugin, [
{
filename: "[path].gz[query]",
algorithm: "gzip",
test: new RegExp(
"\\.(" + productionGzipExtensions.join("|") + ")$"
),
threshold: 8192,
minRatio: 0.8,
},
])
.end();
config.module
.rule("images")
.use("image-webpack-loader")
.loader("image-webpack-loader")
.options({
bypassOnDebug: true,
})
.end();
});
if (build7z) {
config.when(process.env.NODE_ENV === "production", (config) => {
config
.plugin("fileManager")
.use(FileManagerPlugin, [
{
onEnd: {
delete: [`./${outputDir}/video`, `./${outputDir}/data`],
archive: [
{
source: `./${outputDir}`,
destination: `./${outputDir}/${abbreviation}_${outputDir}_${date}.7z`,
},
],
},
},
])
.end();
});
}
},
runtimeCompiler: true,
productionSourceMap: false,
css: {
requireModuleExtension: true,
sourceMap: true,
loaderOptions: {
scss: {
/*sass-loader 8.0语法 */
//prependData: '@import "~@/styles/variables.scss";',
/*sass-loader 9.0写法,感谢github用户 shaonialife*/
additionalData(content, loaderContext) {
const { resourcePath, rootContext } = loaderContext;
const relativePath = path.relative(rootContext, resourcePath);
if (
relativePath.replace(/\\/g, "/") !== "src/styles/variables.scss"
) {
return '@import "~@/styles/variables.scss";' + content;
}
return content;
},
},
},
},
};
"use strict";
const webpackConfig = require("@vue/cli-service/webpack.config.js");
module.exports = webpackConfig;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment