17
									
								
								.babelrc
									
									
									
									
									
								
							
							
						
						@@ -1,17 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "presets": [
 | 
					 | 
				
			||||||
    ["env", {
 | 
					 | 
				
			||||||
      "modules": false,
 | 
					 | 
				
			||||||
      "targets": {
 | 
					 | 
				
			||||||
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }],
 | 
					 | 
				
			||||||
    "stage-2"
 | 
					 | 
				
			||||||
  ],
 | 
					 | 
				
			||||||
  "plugins": ["transform-vue-jsx", "transform-runtime"],
 | 
					 | 
				
			||||||
  "env": {
 | 
					 | 
				
			||||||
    "development":{
 | 
					 | 
				
			||||||
      "plugins": ["dynamic-import-node"]
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										14
									
								
								.env.development
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					# just a flag
 | 
				
			||||||
 | 
					ENV = 'development'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# base api
 | 
				
			||||||
 | 
					VUE_APP_BASE_API = '/dev-api'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
 | 
				
			||||||
 | 
					# to control whether the babel-plugin-dynamic-import-node plugin is enabled.
 | 
				
			||||||
 | 
					# It only does one thing by converting all import() to require().
 | 
				
			||||||
 | 
					# This configuration can significantly increase the speed of hot updates,
 | 
				
			||||||
 | 
					# when you have a large number of pages.
 | 
				
			||||||
 | 
					# Detail:  https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/babel-preset-app/index.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VUE_CLI_BABEL_TRANSPILE_MODULES = true
 | 
				
			||||||
							
								
								
									
										6
									
								
								.env.production
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					# just a flag
 | 
				
			||||||
 | 
					ENV = 'production'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# base api
 | 
				
			||||||
 | 
					VUE_APP_BASE_API = '/prod-api'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										8
									
								
								.env.staging
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					NODE_ENV = production
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# just a flag
 | 
				
			||||||
 | 
					ENV = 'staging'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# base api
 | 
				
			||||||
 | 
					VUE_APP_BASE_API = '/stage-api'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
build/*.js
 | 
					build/*.js
 | 
				
			||||||
config/*.js
 | 
					 | 
				
			||||||
src/assets
 | 
					src/assets
 | 
				
			||||||
 | 
					public
 | 
				
			||||||
 | 
					dist
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,10 @@ module.exports = {
 | 
				
			|||||||
        "allowFirstLine": false
 | 
					        "allowFirstLine": false
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }],
 | 
					    }],
 | 
				
			||||||
 | 
					    "vue/singleline-html-element-content-newline": "off",
 | 
				
			||||||
 | 
					    "vue/multiline-html-element-content-newline":"off",
 | 
				
			||||||
    "vue/name-property-casing": ["error", "PascalCase"],
 | 
					    "vue/name-property-casing": ["error", "PascalCase"],
 | 
				
			||||||
 | 
					    "vue/no-v-html": "off",
 | 
				
			||||||
    'accessor-pairs': 2,
 | 
					    'accessor-pairs': 2,
 | 
				
			||||||
    'arrow-spacing': [2, {
 | 
					    'arrow-spacing': [2, {
 | 
				
			||||||
      'before': true,
 | 
					      'before': true,
 | 
				
			||||||
@@ -44,7 +47,7 @@ module.exports = {
 | 
				
			|||||||
    'curly': [2, 'multi-line'],
 | 
					    'curly': [2, 'multi-line'],
 | 
				
			||||||
    'dot-location': [2, 'property'],
 | 
					    'dot-location': [2, 'property'],
 | 
				
			||||||
    'eol-last': 2,
 | 
					    'eol-last': 2,
 | 
				
			||||||
    'eqeqeq': [2, 'allow-null'],
 | 
					    'eqeqeq': ["error", "always", {"null": "ignore"}],
 | 
				
			||||||
    'generator-star-spacing': [2, {
 | 
					    'generator-star-spacing': [2, {
 | 
				
			||||||
      'before': true,
 | 
					      'before': true,
 | 
				
			||||||
      'after': true
 | 
					      'after': true
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -6,8 +6,8 @@ yarn-debug.log*
 | 
				
			|||||||
yarn-error.log*
 | 
					yarn-error.log*
 | 
				
			||||||
**/*.log
 | 
					**/*.log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test/unit/coverage
 | 
					tests/**/coverage/
 | 
				
			||||||
test/e2e/reports
 | 
					tests/e2e/reports
 | 
				
			||||||
selenium-debug.log
 | 
					selenium-debug.log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Editor directories and files
 | 
					# Editor directories and files
 | 
				
			||||||
@@ -17,5 +17,7 @@ selenium-debug.log
 | 
				
			|||||||
*.ntvs*
 | 
					*.ntvs*
 | 
				
			||||||
*.njsproj
 | 
					*.njsproj
 | 
				
			||||||
*.sln
 | 
					*.sln
 | 
				
			||||||
 | 
					*.local
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package-lock.json
 | 
					package-lock.json
 | 
				
			||||||
 | 
					yarn.lock
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
  "plugins": {
 | 
					  "plugins": {
 | 
				
			||||||
    "postcss-import": {},
 | 
					 | 
				
			||||||
    "postcss-url": {},
 | 
					 | 
				
			||||||
    // to edit target browsers: use "browserslist" field in package.json
 | 
					    // to edit target browsers: use "browserslist" field in package.json
 | 
				
			||||||
    "autoprefixer": {}
 | 
					    "autoprefixer": {}
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										49
									
								
								README.md
									
									
									
									
									
								
							
							
						
						@@ -4,10 +4,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<p align="center">
 | 
					<p align="center">
 | 
				
			||||||
  <a href="https://github.com/vuejs/vue">
 | 
					  <a href="https://github.com/vuejs/vue">
 | 
				
			||||||
    <img src="https://img.shields.io/badge/vue-2.5.17-brightgreen.svg" alt="vue">
 | 
					    <img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
 | 
				
			||||||
  </a>
 | 
					  </a>
 | 
				
			||||||
  <a href="https://github.com/ElemeFE/element">
 | 
					  <a href="https://github.com/ElemeFE/element">
 | 
				
			||||||
    <img src="https://img.shields.io/badge/element--ui-2.4.11-brightgreen.svg" alt="element-ui">
 | 
					    <img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
 | 
				
			||||||
  </a>
 | 
					  </a>
 | 
				
			||||||
  <a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
 | 
					  <a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
 | 
				
			||||||
    <img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
 | 
					    <img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
 | 
				
			||||||
@@ -30,7 +30,7 @@ English | [简体中文](./README.zh-CN.md)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Introduction
 | 
					## Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[vue-element-admin](http://panjiachen.github.io/vue-element-admin) is a front-end management background integration solution. It based on [vue](https://github.com/vuejs/vue) and use the UI Toolkit [element](https://github.com/ElemeFE/element).
 | 
					[vue-element-admin](http://panjiachen.github.io/vue-element-admin) is a production-ready front-end solution for admin interfaces. It based on [vue](https://github.com/vuejs/vue) and use the UI Toolkit [element-ui](https://github.com/ElemeFE/element).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
It is a magical vue admin based on the newest development stack of vue, built-in i18n solution, typical templates for enterprise applications, lots of awesome features. It helps you build a large complex Single-Page Applications. I believe whatever your needs are, this project will help you.
 | 
					It is a magical vue admin based on the newest development stack of vue, built-in i18n solution, typical templates for enterprise applications, lots of awesome features. It helps you build a large complex Single-Page Applications. I believe whatever your needs are, this project will help you.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -40,36 +40,31 @@ It is a magical vue admin based on the newest development stack of vue, built-in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
- [Gitter](https://gitter.im/vue-element-admin/discuss)
 | 
					- [Gitter](https://gitter.im/vue-element-admin/discuss)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- [Donate](https://panjiachen.github.io/vue-element-admin-site/donate/)
 | 
					- [Donate](https://panjiachen.github.io/vue-element-admin-site/donate/)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 国内用户可访问该地址在线预览
 | 
					- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**This project is positioned as a background integration solution and is not suitable for secondary development as a basic template.**
 | 
					- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 国内用户可访问该地址在线预览
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Base template recommends using: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
 | 
					- Base template recommends using: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
 | 
				
			||||||
- Desktop: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
 | 
					- Desktop: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
 | 
				
			||||||
- Typescript: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
 | 
					- Typescript: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**This project does not support low version browsers (e.g. IE). Please add polyfill yourself if you need them.**
 | 
					**The current version is `4.0-beta`. If you find a problem, please put [issue](https://github.com/PanJiaChen/vue-element-admin/issues/new). If you want to use the old version - stable version, you can switch branch to [tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0)**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Note: This project uses element-ui@2.3.0+ version, so the minimum compatible vue@2.5.0+**
 | 
					**This project does not support low version browsers (e.g. IE). Please add polyfill by yourself.**
 | 
				
			||||||
 | 
					 | 
				
			||||||
**Start using `webpack4` from `v3.8.0`. If you still want to continue using `webpack3`, please use this branch [webpack3](https://github.com/PanJiaChen/vue-element-admin/tree/webpack3)**
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Preparation
 | 
					## Preparation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You need to install [node](http://nodejs.org/) and [git](https://git-scm.com/) locally. The project is based on [ES2015+](http://es6.ruanyifeng.com/), [vue](https://cn.vuejs.org/index.html), [vuex](https://vuex.vuejs.org/zh-cn/), [vue-router](https://router.vuejs.org/zh-cn/), [axios](https://github.com/axios/axios) and [element-ui](https://github.com/ElemeFE/element), all request data is simulated using [Mock.js](https://github.com/nuysoft/Mock).
 | 
					You need to install [node](http://nodejs.org/) and [git](https://git-scm.com/) locally. The project is based on [ES2015+](http://es6.ruanyifeng.com/), [vue](https://cn.vuejs.org/index.html), [vuex](https://vuex.vuejs.org/zh-cn/), [vue-router](https://router.vuejs.org/zh-cn/), [vue-cli](https://github.com/vuejs/vue-cli) , [axios](https://github.com/axios/axios) and [element-ui](https://github.com/ElemeFE/element), all request data is simulated using [Mock.js](https://github.com/nuysoft/Mock).
 | 
				
			||||||
Understanding and learning this knowledge in advance will greatly help the use of this project.
 | 
					Understanding and learning this knowledge in advance will greatly help the use of this project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 <p align="center">
 | 
					 <p align="center">
 | 
				
			||||||
  <img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
 | 
					  <img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
 | 
				
			||||||
</p>
 | 
					</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Sponsors
 | 
					## Sponsors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
 | 
					Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
 | 
					<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
 | 
				
			||||||
@@ -82,6 +77,7 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
 | 
				
			|||||||
- Permission Authentication
 | 
					- Permission Authentication
 | 
				
			||||||
  - Page permission
 | 
					  - Page permission
 | 
				
			||||||
  - Directive permission
 | 
					  - Directive permission
 | 
				
			||||||
 | 
					  - Permission configuration page
 | 
				
			||||||
  - Two-step login
 | 
					  - Two-step login
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Multi-environment build
 | 
					- Multi-environment build
 | 
				
			||||||
@@ -105,14 +101,13 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
- Excel
 | 
					- Excel
 | 
				
			||||||
  - Export Excel
 | 
					  - Export Excel
 | 
				
			||||||
  - Export zip
 | 
					 | 
				
			||||||
  - Upload Excel
 | 
					  - Upload Excel
 | 
				
			||||||
  - Visualization Excel
 | 
					  - Visualization Excel
 | 
				
			||||||
 | 
					  - Export zip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Table
 | 
					- Table
 | 
				
			||||||
  - Dynamic Table
 | 
					  - Dynamic Table
 | 
				
			||||||
  - Drag And Drop Table
 | 
					  - Drag And Drop Table
 | 
				
			||||||
  - Tree Table
 | 
					 | 
				
			||||||
  - Inline Edit Table
 | 
					  - Inline Edit Table
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Error Page
 | 
					- Error Page
 | 
				
			||||||
@@ -146,6 +141,9 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
 | 
				
			|||||||
# clone the project
 | 
					# clone the project
 | 
				
			||||||
git clone https://github.com/PanJiaChen/vue-element-admin.git
 | 
					git clone https://github.com/PanJiaChen/vue-element-admin.git
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# enter the project directory
 | 
				
			||||||
 | 
					cd vue-element-admin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# install dependency
 | 
					# install dependency
 | 
				
			||||||
npm install
 | 
					npm install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -153,13 +151,13 @@ npm install
 | 
				
			|||||||
npm run dev
 | 
					npm run dev
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This will automatically open http://localhost:9527.
 | 
					This will automatically open http://localhost:9527
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Build
 | 
					## Build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
# build for test environment
 | 
					# build for test environment
 | 
				
			||||||
npm run build:sit
 | 
					npm run build:stage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# build for production environment
 | 
					# build for production environment
 | 
				
			||||||
npm run build:prod
 | 
					npm run build:prod
 | 
				
			||||||
@@ -168,19 +166,16 @@ npm run build:prod
 | 
				
			|||||||
## Advanced
 | 
					## Advanced
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
# --report to build with bundle size analytics
 | 
					# preview the release environment effect
 | 
				
			||||||
npm run build:prod --report
 | 
					npm run preview
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --generate a bundle size analytics. default: bundle-report.html
 | 
					# preview the release environment effect + static resource analysis
 | 
				
			||||||
npm run build:prod --generate_report
 | 
					npm run preview -- --report
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --preview to start a server in local to preview
 | 
					# code format check
 | 
				
			||||||
npm run build:prod --preview
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# lint code
 | 
					 | 
				
			||||||
npm run lint
 | 
					npm run lint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# auto fix
 | 
					# code format check and auto fix
 | 
				
			||||||
npm run lint -- --fix
 | 
					npm run lint -- --fix
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,10 +4,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<p align="center">
 | 
					<p align="center">
 | 
				
			||||||
  <a href="https://github.com/vuejs/vue">
 | 
					  <a href="https://github.com/vuejs/vue">
 | 
				
			||||||
    <img src="https://img.shields.io/badge/vue-2.5.10-brightgreen.svg" alt="vue">
 | 
					    <img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
 | 
				
			||||||
  </a>
 | 
					  </a>
 | 
				
			||||||
  <a href="https://github.com/ElemeFE/element">
 | 
					  <a href="https://github.com/ElemeFE/element">
 | 
				
			||||||
    <img src="https://img.shields.io/badge/element--ui-2.4.11-brightgreen.svg" alt="element-ui">
 | 
					    <img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
 | 
				
			||||||
  </a>
 | 
					  </a>
 | 
				
			||||||
  <a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
 | 
					  <a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
 | 
				
			||||||
    <img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
 | 
					    <img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
 | 
				
			||||||
@@ -30,41 +30,37 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## 简介
 | 
					## 简介
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[vue-element-admin](http://panjiachen.github.io/vue-element-admin) 是一个后台集成解决方案,它基于 [vue](https://github.com/vuejs/vue) 和 [element](https://github.com/ElemeFE/element)。它使用了最新的前端技术栈,内置了 i18 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。
 | 
					[vue-element-admin](http://panjiachen.github.io/vue-element-admin) 是一个后台前端解决方案,它基于 [vue](https://github.com/vuejs/vue) 和 [element-ui](https://github.com/ElemeFE/element)实现。它使用了最新的前端技术栈,内置了 i18n 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [在线访问](http://panjiachen.github.io/vue-element-admin)
 | 
					- [在线预览](http://panjiachen.github.io/vue-element-admin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
 | 
					- [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [Gitter 讨论组](https://gitter.im/vue-element-admin/discuss)
 | 
					- [Gitter 讨论组](https://gitter.im/vue-element-admin/discuss)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- [Donate](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate)
 | 
					- [Donate](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 国内用户可访问该地址在线预览
 | 
					- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [国内访问文档](https://panjiachen.gitee.io/vue-element-admin-site/zh/) 方便没翻墙的用户查看文档
 | 
					- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 在线预览(国内用户可访问该地址)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**本项目的定位是后台集成方案,不适合当基础模板来开发。**
 | 
					- [国内访问文档](https://panjiachen.gitee.io/vue-element-admin-site/zh/) 文档(方便没翻墙的用户查看)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- 模板建议使用: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
 | 
					- 基础模板建议使用: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
 | 
				
			||||||
- 桌面端: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
 | 
					- 桌面端: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
 | 
				
			||||||
- Typescript版: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (鸣谢: [@Armour](https://github.com/Armour))
 | 
					- Typescript 版: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (鸣谢: [@Armour](https://github.com/Armour))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
群主 **[圈子](https://jianshiapp.com/circles/1209)** 楼主会经常分享一些技术相关的东西,或者加入[qq 群](https://github.com/PanJiaChen/vue-element-admin/issues/602)
 | 
					**目前版本为 `4.0-beta`,若发现问题,欢迎提[issue](https://github.com/PanJiaChen/vue-element-admin/issues/new)。若你想使用旧版本-稳定版,可以切换分支到[tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0)**
 | 
				
			||||||
 | 
					 | 
				
			||||||
**注意:该项目使用 element-ui@2.3.0+ 版本,所以最低兼容 vue@2.5.0+**
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
**从`v3.8.0`开始使用`webpack4`。所以若还想使用`webpack3`开发,请使用该分支[webpack3](https://github.com/PanJiaChen/vue-element-admin/tree/webpack3)**
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
**该项目不支持低版本浏览器(如 ie),有需求请自行添加 polyfill [详情](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)**
 | 
					**该项目不支持低版本浏览器(如 ie),有需求请自行添加 polyfill [详情](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					群主 **[圈子](https://jianshiapp.com/circles/1209)** 群主会经常分享一些技术相关的东西,或者加入 [qq 群](https://github.com/PanJiaChen/vue-element-admin/issues/602) 或者关注 [微博](https://weibo.com/u/3423485724?is_all=1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 前序准备
 | 
					## 前序准备
 | 
				
			||||||
 | 
					
 | 
				
			||||||
你需要在本地安装 [node](http://nodejs.org/) 和 [git](https://git-scm.com/)。本项目技术栈基于 [ES2015+](http://es6.ruanyifeng.com/)、[vue](https://cn.vuejs.org/index.html)、[vuex](https://vuex.vuejs.org/zh-cn/)、[vue-router](https://router.vuejs.org/zh-cn/) 、[axios](https://github.com/axios/axios) 和 [element-ui](https://github.com/ElemeFE/element),所有的请求数据都使用[Mock.js](https://github.com/nuysoft/Mock)模拟,提前了解和学习这些知识会对使用本项目有很大的帮助。
 | 
					你需要在本地安装 [node](http://nodejs.org/) 和 [git](https://git-scm.com/)。本项目技术栈基于 [ES2015+](http://es6.ruanyifeng.com/)、[vue](https://cn.vuejs.org/index.html)、[vuex](https://vuex.vuejs.org/zh-cn/)、[vue-router](https://router.vuejs.org/zh-cn/) 、[vue-cli](https://github.com/vuejs/vue-cli) 、[axios](https://github.com/axios/axios) 和 [element-ui](https://github.com/ElemeFE/element),所有的请求数据都使用[Mock.js](https://github.com/nuysoft/Mock)进行模拟,提前了解和学习这些知识会对使用本项目有很大的帮助。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
同时配套一个系列的教程文章,如何从零构建后一个完整的后台项目,建议大家先看完这些文章再来实践本项目
 | 
					同时配套了系列教程文章,如何从零构建后一个完整的后台项目,建议大家先看完这些文章再来实践本项目
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
 | 
					- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
 | 
				
			||||||
- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
 | 
					- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
 | 
				
			||||||
@@ -82,6 +78,7 @@
 | 
				
			|||||||
</p>
 | 
					</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Sponsors
 | 
					## Sponsors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
 | 
					Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
 | 
					<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
 | 
				
			||||||
@@ -94,6 +91,7 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
 | 
				
			|||||||
- 权限验证
 | 
					- 权限验证
 | 
				
			||||||
  - 页面权限
 | 
					  - 页面权限
 | 
				
			||||||
  - 指令权限
 | 
					  - 指令权限
 | 
				
			||||||
 | 
					  - 权限配置
 | 
				
			||||||
  - 二步登录
 | 
					  - 二步登录
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- 多环境发布
 | 
					- 多环境发布
 | 
				
			||||||
@@ -106,7 +104,7 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
 | 
				
			|||||||
  - 动态面包屑
 | 
					  - 动态面包屑
 | 
				
			||||||
  - 快捷导航(标签页)
 | 
					  - 快捷导航(标签页)
 | 
				
			||||||
  - Svg Sprite 图标
 | 
					  - Svg Sprite 图标
 | 
				
			||||||
  - 本地mock数据
 | 
					  - 本地/后端 mock 数据
 | 
				
			||||||
  - Screenfull全屏
 | 
					  - Screenfull全屏
 | 
				
			||||||
  - 自适应收缩侧边栏
 | 
					  - 自适应收缩侧边栏
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -117,14 +115,13 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
- Excel
 | 
					- Excel
 | 
				
			||||||
  - 导出excel
 | 
					  - 导出excel
 | 
				
			||||||
  - 导出zip
 | 
					 | 
				
			||||||
  - 导入excel
 | 
					  - 导入excel
 | 
				
			||||||
  - 前端可视化excel
 | 
					  - 前端可视化excel
 | 
				
			||||||
 | 
					  - 导出zip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- 表格
 | 
					- 表格
 | 
				
			||||||
  - 动态表格
 | 
					  - 动态表格
 | 
				
			||||||
  - 拖拽表格
 | 
					  - 拖拽表格
 | 
				
			||||||
  - 树形表格
 | 
					 | 
				
			||||||
  - 内联编辑
 | 
					  - 内联编辑
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- 错误页面
 | 
					- 错误页面
 | 
				
			||||||
@@ -158,6 +155,9 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
 | 
				
			|||||||
# 克隆项目
 | 
					# 克隆项目
 | 
				
			||||||
git clone https://github.com/PanJiaChen/vue-element-admin.git
 | 
					git clone https://github.com/PanJiaChen/vue-element-admin.git
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 进入项目目录
 | 
				
			||||||
 | 
					cd vue-element-admin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# 安装依赖
 | 
					# 安装依赖
 | 
				
			||||||
npm install
 | 
					npm install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -174,7 +174,7 @@ npm run dev
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
# 构建测试环境
 | 
					# 构建测试环境
 | 
				
			||||||
npm run build:sit
 | 
					npm run build:stage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# 构建生产环境
 | 
					# 构建生产环境
 | 
				
			||||||
npm run build:prod
 | 
					npm run build:prod
 | 
				
			||||||
@@ -183,19 +183,16 @@ npm run build:prod
 | 
				
			|||||||
## 其它
 | 
					## 其它
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
# --report to build with bundle size analytics
 | 
					# 预览发布环境效果
 | 
				
			||||||
npm run build:prod
 | 
					npm run preview
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --generate a bundle size analytics. default: bundle-report.html
 | 
					# 预览发布环境效果 + 静态资源分析
 | 
				
			||||||
npm run build:prod --generate_report
 | 
					npm run preview -- --report
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --preview to start a server in local to preview
 | 
					# 代码格式检查
 | 
				
			||||||
npm run build:prod --preview
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# lint code
 | 
					 | 
				
			||||||
npm run lint
 | 
					npm run lint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# auto fix
 | 
					# 代码格式检查并自动修复
 | 
				
			||||||
npm run lint -- --fix
 | 
					npm run lint -- --fix
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -218,6 +215,8 @@ Detailed changes for each release are documented in the [release notes](https://
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[Paypal Me](https://www.paypal.me/panfree23)
 | 
					[Paypal Me](https://www.paypal.me/panfree23)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Buy me a coffee](https://www.buymeacoffee.com/Pan)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Browsers support
 | 
					## Browsers support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Modern browsers and Internet Explorer 10+.
 | 
					Modern browsers and Internet Explorer 10+.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								babel.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					  presets: [
 | 
				
			||||||
 | 
					    '@vue/app'
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,67 +0,0 @@
 | 
				
			|||||||
'use strict'
 | 
					 | 
				
			||||||
require('./check-versions')()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const ora = require('ora')
 | 
					 | 
				
			||||||
const rm = require('rimraf')
 | 
					 | 
				
			||||||
const path = require('path')
 | 
					 | 
				
			||||||
const chalk = require('chalk')
 | 
					 | 
				
			||||||
const webpack = require('webpack')
 | 
					 | 
				
			||||||
const config = require('../config')
 | 
					 | 
				
			||||||
const webpackConfig = require('./webpack.prod.conf')
 | 
					 | 
				
			||||||
var connect = require('connect')
 | 
					 | 
				
			||||||
var serveStatic = require('serve-static')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const spinner = ora(
 | 
					 | 
				
			||||||
  'building for ' + process.env.env_config + ' environment...'
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
spinner.start()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
 | 
					 | 
				
			||||||
  if (err) throw err
 | 
					 | 
				
			||||||
  webpack(webpackConfig, (err, stats) => {
 | 
					 | 
				
			||||||
    spinner.stop()
 | 
					 | 
				
			||||||
    if (err) throw err
 | 
					 | 
				
			||||||
    process.stdout.write(
 | 
					 | 
				
			||||||
      stats.toString({
 | 
					 | 
				
			||||||
        colors: true,
 | 
					 | 
				
			||||||
        modules: false,
 | 
					 | 
				
			||||||
        children: false,
 | 
					 | 
				
			||||||
        chunks: false,
 | 
					 | 
				
			||||||
        chunkModules: false
 | 
					 | 
				
			||||||
      }) + '\n\n'
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (stats.hasErrors()) {
 | 
					 | 
				
			||||||
      console.log(chalk.red(' Build failed with errors.\n'))
 | 
					 | 
				
			||||||
      process.exit(1)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    console.log(chalk.cyan(' Build complete.\n'))
 | 
					 | 
				
			||||||
    console.log(
 | 
					 | 
				
			||||||
      chalk.yellow(
 | 
					 | 
				
			||||||
        ' Tip: built files are meant to be served over an HTTP server.\n' +
 | 
					 | 
				
			||||||
          " Opening index.html over file:// won't work.\n"
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (process.env.npm_config_preview) {
 | 
					 | 
				
			||||||
      const port = 9526
 | 
					 | 
				
			||||||
      const host = 'http://localhost:' + port
 | 
					 | 
				
			||||||
      const basePath = config.build.assetsPublicPath
 | 
					 | 
				
			||||||
      const app = connect()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      app.use(
 | 
					 | 
				
			||||||
        basePath,
 | 
					 | 
				
			||||||
        serveStatic('./dist', {
 | 
					 | 
				
			||||||
          index: ['index.html', '/']
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      app.listen(port, function() {
 | 
					 | 
				
			||||||
        console.log(
 | 
					 | 
				
			||||||
          chalk.green(`> Listening at  http://localhost:${port}${basePath}`)
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
@@ -1,64 +0,0 @@
 | 
				
			|||||||
'use strict'
 | 
					 | 
				
			||||||
const chalk = require('chalk')
 | 
					 | 
				
			||||||
const semver = require('semver')
 | 
					 | 
				
			||||||
const packageConfig = require('../package.json')
 | 
					 | 
				
			||||||
const shell = require('shelljs')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function exec(cmd) {
 | 
					 | 
				
			||||||
  return require('child_process')
 | 
					 | 
				
			||||||
    .execSync(cmd)
 | 
					 | 
				
			||||||
    .toString()
 | 
					 | 
				
			||||||
    .trim()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const versionRequirements = [
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    name: 'node',
 | 
					 | 
				
			||||||
    currentVersion: semver.clean(process.version),
 | 
					 | 
				
			||||||
    versionRequirement: packageConfig.engines.node
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if (shell.which('npm')) {
 | 
					 | 
				
			||||||
  versionRequirements.push({
 | 
					 | 
				
			||||||
    name: 'npm',
 | 
					 | 
				
			||||||
    currentVersion: exec('npm --version'),
 | 
					 | 
				
			||||||
    versionRequirement: packageConfig.engines.npm
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = function() {
 | 
					 | 
				
			||||||
  const warnings = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (let i = 0; i < versionRequirements.length; i++) {
 | 
					 | 
				
			||||||
    const mod = versionRequirements[i]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
 | 
					 | 
				
			||||||
      warnings.push(
 | 
					 | 
				
			||||||
        mod.name +
 | 
					 | 
				
			||||||
          ': ' +
 | 
					 | 
				
			||||||
          chalk.red(mod.currentVersion) +
 | 
					 | 
				
			||||||
          ' should be ' +
 | 
					 | 
				
			||||||
          chalk.green(mod.versionRequirement)
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (warnings.length) {
 | 
					 | 
				
			||||||
    console.log('')
 | 
					 | 
				
			||||||
    console.log(
 | 
					 | 
				
			||||||
      chalk.yellow(
 | 
					 | 
				
			||||||
        'To use this template, you must update following to modules:'
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    console.log()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (let i = 0; i < warnings.length; i++) {
 | 
					 | 
				
			||||||
      const warning = warnings[i]
 | 
					 | 
				
			||||||
      console.log('  ' + warning)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    console.log()
 | 
					 | 
				
			||||||
    process.exit(1)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										35
									
								
								build/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					const { run } = require('runjs')
 | 
				
			||||||
 | 
					const chalk = require('chalk')
 | 
				
			||||||
 | 
					const config = require('../vue.config.js')
 | 
				
			||||||
 | 
					const rawArgv = process.argv.slice(2)
 | 
				
			||||||
 | 
					const args = rawArgv.join(' ')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
 | 
				
			||||||
 | 
					  const report = rawArgv.includes('--report')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  run(`vue-cli-service build ${args}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const port = 9526
 | 
				
			||||||
 | 
					  const publicPath = config.publicPath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var connect = require('connect')
 | 
				
			||||||
 | 
					  var serveStatic = require('serve-static')
 | 
				
			||||||
 | 
					  const app = connect()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  app.use(
 | 
				
			||||||
 | 
					    publicPath,
 | 
				
			||||||
 | 
					    serveStatic('./dist', {
 | 
				
			||||||
 | 
					      index: ['index.html', '/']
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  app.listen(port, function () {
 | 
				
			||||||
 | 
					    console.log(chalk.green(`> Preview at  http://localhost:${port}${publicPath}`))
 | 
				
			||||||
 | 
					    if (report) {
 | 
				
			||||||
 | 
					      console.log(chalk.green(`> Report at  http://localhost:${port}${publicPath}/report.html`))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
					  run(`vue-cli-service build ${args}`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								build/logo.png
									
									
									
									
									
								
							
							
						
						| 
		 Before Width: | Height: | Size: 6.7 KiB  | 
							
								
								
									
										108
									
								
								build/utils.js
									
									
									
									
									
								
							
							
						
						@@ -1,108 +0,0 @@
 | 
				
			|||||||
'use strict'
 | 
					 | 
				
			||||||
const path = require('path')
 | 
					 | 
				
			||||||
const config = require('../config')
 | 
					 | 
				
			||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
 | 
					 | 
				
			||||||
const packageConfig = require('../package.json')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.assetsPath = function(_path) {
 | 
					 | 
				
			||||||
  const assetsSubDirectory =
 | 
					 | 
				
			||||||
    process.env.NODE_ENV === 'production'
 | 
					 | 
				
			||||||
      ? config.build.assetsSubDirectory
 | 
					 | 
				
			||||||
      : config.dev.assetsSubDirectory
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return path.posix.join(assetsSubDirectory, _path)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.cssLoaders = function(options) {
 | 
					 | 
				
			||||||
  options = options || {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const cssLoader = {
 | 
					 | 
				
			||||||
    loader: 'css-loader',
 | 
					 | 
				
			||||||
    options: {
 | 
					 | 
				
			||||||
      sourceMap: options.sourceMap
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const postcssLoader = {
 | 
					 | 
				
			||||||
    loader: 'postcss-loader',
 | 
					 | 
				
			||||||
    options: {
 | 
					 | 
				
			||||||
      sourceMap: options.sourceMap
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // generate loader string to be used with extract text plugin
 | 
					 | 
				
			||||||
  function generateLoaders(loader, loaderOptions) {
 | 
					 | 
				
			||||||
    const loaders = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Extract CSS when that option is specified
 | 
					 | 
				
			||||||
    // (which is the case during production build)
 | 
					 | 
				
			||||||
    if (options.extract) {
 | 
					 | 
				
			||||||
      loaders.push(MiniCssExtractPlugin.loader)
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      loaders.push('vue-style-loader')
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    loaders.push(cssLoader)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (options.usePostCSS) {
 | 
					 | 
				
			||||||
      loaders.push(postcssLoader)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (loader) {
 | 
					 | 
				
			||||||
      loaders.push({
 | 
					 | 
				
			||||||
        loader: loader + '-loader',
 | 
					 | 
				
			||||||
        options: Object.assign({}, loaderOptions, {
 | 
					 | 
				
			||||||
          sourceMap: options.sourceMap
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return loaders
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
 | 
					 | 
				
			||||||
  return {
 | 
					 | 
				
			||||||
    css: generateLoaders(),
 | 
					 | 
				
			||||||
    postcss: generateLoaders(),
 | 
					 | 
				
			||||||
    less: generateLoaders('less'),
 | 
					 | 
				
			||||||
    sass: generateLoaders('sass', {
 | 
					 | 
				
			||||||
      indentedSyntax: true
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
    scss: generateLoaders('sass'),
 | 
					 | 
				
			||||||
    stylus: generateLoaders('stylus'),
 | 
					 | 
				
			||||||
    styl: generateLoaders('stylus')
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Generate loaders for standalone style files (outside of .vue)
 | 
					 | 
				
			||||||
exports.styleLoaders = function(options) {
 | 
					 | 
				
			||||||
  const output = []
 | 
					 | 
				
			||||||
  const loaders = exports.cssLoaders(options)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (const extension in loaders) {
 | 
					 | 
				
			||||||
    const loader = loaders[extension]
 | 
					 | 
				
			||||||
    output.push({
 | 
					 | 
				
			||||||
      test: new RegExp('\\.' + extension + '$'),
 | 
					 | 
				
			||||||
      use: loader
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return output
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
exports.createNotifierCallback = () => {
 | 
					 | 
				
			||||||
  const notifier = require('node-notifier')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return (severity, errors) => {
 | 
					 | 
				
			||||||
    if (severity !== 'error') return
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const error = errors[0]
 | 
					 | 
				
			||||||
    const filename = error.file && error.file.split('!').pop()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    notifier.notify({
 | 
					 | 
				
			||||||
      title: packageConfig.name,
 | 
					 | 
				
			||||||
      message: severity + ': ' + error.name,
 | 
					 | 
				
			||||||
      subtitle: filename || '',
 | 
					 | 
				
			||||||
      icon: path.join(__dirname, 'logo.png')
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
'use strict'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
  //You can set the vue-loader configuration by yourself.
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,107 +0,0 @@
 | 
				
			|||||||
'use strict'
 | 
					 | 
				
			||||||
const path = require('path')
 | 
					 | 
				
			||||||
const utils = require('./utils')
 | 
					 | 
				
			||||||
const config = require('../config')
 | 
					 | 
				
			||||||
const { VueLoaderPlugin } = require('vue-loader')
 | 
					 | 
				
			||||||
const vueLoaderConfig = require('./vue-loader.conf')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function resolve(dir) {
 | 
					 | 
				
			||||||
  return path.join(__dirname, '..', dir)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const createLintingRule = () => ({
 | 
					 | 
				
			||||||
  test: /\.(js|vue)$/,
 | 
					 | 
				
			||||||
  loader: 'eslint-loader',
 | 
					 | 
				
			||||||
  enforce: 'pre',
 | 
					 | 
				
			||||||
  include: [resolve('src'), resolve('test')],
 | 
					 | 
				
			||||||
  options: {
 | 
					 | 
				
			||||||
    formatter: require('eslint-friendly-formatter'),
 | 
					 | 
				
			||||||
    emitWarning: !config.dev.showEslintErrorsInOverlay
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
  context: path.resolve(__dirname, '../'),
 | 
					 | 
				
			||||||
  entry: {
 | 
					 | 
				
			||||||
    app: './src/main.js'
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  output: {
 | 
					 | 
				
			||||||
    path: config.build.assetsRoot,
 | 
					 | 
				
			||||||
    filename: '[name].js',
 | 
					 | 
				
			||||||
    publicPath:
 | 
					 | 
				
			||||||
      process.env.NODE_ENV === 'production'
 | 
					 | 
				
			||||||
        ? config.build.assetsPublicPath
 | 
					 | 
				
			||||||
        : config.dev.assetsPublicPath
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  resolve: {
 | 
					 | 
				
			||||||
    extensions: ['.js', '.vue', '.json'],
 | 
					 | 
				
			||||||
    alias: {
 | 
					 | 
				
			||||||
      '@': resolve('src')
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  module: {
 | 
					 | 
				
			||||||
    rules: [
 | 
					 | 
				
			||||||
      ...(config.dev.useEslint ? [createLintingRule()] : []),
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        test: /\.vue$/,
 | 
					 | 
				
			||||||
        loader: 'vue-loader',
 | 
					 | 
				
			||||||
        options: vueLoaderConfig
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        test: /\.js$/,
 | 
					 | 
				
			||||||
        loader: 'babel-loader?cacheDirectory',
 | 
					 | 
				
			||||||
        include: [
 | 
					 | 
				
			||||||
          resolve('src'),
 | 
					 | 
				
			||||||
          resolve('test'),
 | 
					 | 
				
			||||||
          resolve('node_modules/webpack-dev-server/client')
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        test: /\.svg$/,
 | 
					 | 
				
			||||||
        loader: 'svg-sprite-loader',
 | 
					 | 
				
			||||||
        include: [resolve('src/icons')],
 | 
					 | 
				
			||||||
        options: {
 | 
					 | 
				
			||||||
          symbolId: 'icon-[name]'
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
 | 
					 | 
				
			||||||
        loader: 'url-loader',
 | 
					 | 
				
			||||||
        exclude: [resolve('src/icons')],
 | 
					 | 
				
			||||||
        options: {
 | 
					 | 
				
			||||||
          limit: 10000,
 | 
					 | 
				
			||||||
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
 | 
					 | 
				
			||||||
        loader: 'url-loader',
 | 
					 | 
				
			||||||
        options: {
 | 
					 | 
				
			||||||
          limit: 10000,
 | 
					 | 
				
			||||||
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
 | 
					 | 
				
			||||||
        loader: 'url-loader',
 | 
					 | 
				
			||||||
        options: {
 | 
					 | 
				
			||||||
          limit: 10000,
 | 
					 | 
				
			||||||
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  plugins: [new VueLoaderPlugin()],
 | 
					 | 
				
			||||||
  node: {
 | 
					 | 
				
			||||||
    // prevent webpack from injecting useless setImmediate polyfill because Vue
 | 
					 | 
				
			||||||
    // source contains it (although only uses it if it's native).
 | 
					 | 
				
			||||||
    setImmediate: false,
 | 
					 | 
				
			||||||
    // prevent webpack from injecting mocks to Node native modules
 | 
					 | 
				
			||||||
    // that does not make sense for the client
 | 
					 | 
				
			||||||
    dgram: 'empty',
 | 
					 | 
				
			||||||
    fs: 'empty',
 | 
					 | 
				
			||||||
    net: 'empty',
 | 
					 | 
				
			||||||
    tls: 'empty',
 | 
					 | 
				
			||||||
    child_process: 'empty'
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,98 +0,0 @@
 | 
				
			|||||||
'use strict'
 | 
					 | 
				
			||||||
const path = require('path')
 | 
					 | 
				
			||||||
const utils = require('./utils')
 | 
					 | 
				
			||||||
const webpack = require('webpack')
 | 
					 | 
				
			||||||
const config = require('../config')
 | 
					 | 
				
			||||||
const merge = require('webpack-merge')
 | 
					 | 
				
			||||||
const baseWebpackConfig = require('./webpack.base.conf')
 | 
					 | 
				
			||||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
 | 
					 | 
				
			||||||
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
 | 
					 | 
				
			||||||
const portfinder = require('portfinder')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function resolve(dir) {
 | 
					 | 
				
			||||||
  return path.join(__dirname, '..', dir)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const HOST = process.env.HOST
 | 
					 | 
				
			||||||
const PORT = process.env.PORT && Number(process.env.PORT)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const devWebpackConfig = merge(baseWebpackConfig, {
 | 
					 | 
				
			||||||
  mode: 'development',
 | 
					 | 
				
			||||||
  module: {
 | 
					 | 
				
			||||||
    rules: utils.styleLoaders({
 | 
					 | 
				
			||||||
      sourceMap: config.dev.cssSourceMap,
 | 
					 | 
				
			||||||
      usePostCSS: true
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  // cheap-module-eval-source-map is faster for development
 | 
					 | 
				
			||||||
  devtool: config.dev.devtool,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // these devServer options should be customized in /config/index.js
 | 
					 | 
				
			||||||
  devServer: {
 | 
					 | 
				
			||||||
    clientLogLevel: 'warning',
 | 
					 | 
				
			||||||
    historyApiFallback: true,
 | 
					 | 
				
			||||||
    hot: true,
 | 
					 | 
				
			||||||
    compress: true,
 | 
					 | 
				
			||||||
    host: HOST || config.dev.host,
 | 
					 | 
				
			||||||
    port: PORT || config.dev.port,
 | 
					 | 
				
			||||||
    open: config.dev.autoOpenBrowser,
 | 
					 | 
				
			||||||
    overlay: config.dev.errorOverlay
 | 
					 | 
				
			||||||
      ? { warnings: false, errors: true }
 | 
					 | 
				
			||||||
      : false,
 | 
					 | 
				
			||||||
    publicPath: config.dev.assetsPublicPath,
 | 
					 | 
				
			||||||
    proxy: config.dev.proxyTable,
 | 
					 | 
				
			||||||
    quiet: true, // necessary for FriendlyErrorsPlugin
 | 
					 | 
				
			||||||
    watchOptions: {
 | 
					 | 
				
			||||||
      poll: config.dev.poll
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  plugins: [
 | 
					 | 
				
			||||||
    new webpack.DefinePlugin({
 | 
					 | 
				
			||||||
      'process.env': require('../config/dev.env')
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
    new webpack.HotModuleReplacementPlugin(),
 | 
					 | 
				
			||||||
    // https://github.com/ampedandwired/html-webpack-plugin
 | 
					 | 
				
			||||||
    new HtmlWebpackPlugin({
 | 
					 | 
				
			||||||
      filename: 'index.html',
 | 
					 | 
				
			||||||
      template: 'index.html',
 | 
					 | 
				
			||||||
      inject: true,
 | 
					 | 
				
			||||||
      favicon: resolve('favicon.ico'),
 | 
					 | 
				
			||||||
      title: 'vue-element-admin',
 | 
					 | 
				
			||||||
      templateParameters: {
 | 
					 | 
				
			||||||
        BASE_URL: config.dev.assetsPublicPath + config.dev.assetsSubDirectory,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
  ]
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = new Promise((resolve, reject) => {
 | 
					 | 
				
			||||||
  portfinder.basePort = process.env.PORT || config.dev.port
 | 
					 | 
				
			||||||
  portfinder.getPort((err, port) => {
 | 
					 | 
				
			||||||
    if (err) {
 | 
					 | 
				
			||||||
      reject(err)
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      // publish the new Port, necessary for e2e tests
 | 
					 | 
				
			||||||
      process.env.PORT = port
 | 
					 | 
				
			||||||
      // add port to devServer config
 | 
					 | 
				
			||||||
      devWebpackConfig.devServer.port = port
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Add FriendlyErrorsPlugin
 | 
					 | 
				
			||||||
      devWebpackConfig.plugins.push(
 | 
					 | 
				
			||||||
        new FriendlyErrorsPlugin({
 | 
					 | 
				
			||||||
          compilationSuccessInfo: {
 | 
					 | 
				
			||||||
            messages: [
 | 
					 | 
				
			||||||
              `Your application is running here: http://${
 | 
					 | 
				
			||||||
                devWebpackConfig.devServer.host
 | 
					 | 
				
			||||||
              }:${port}`
 | 
					 | 
				
			||||||
            ]
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
          onErrors: config.dev.notifyOnErrors
 | 
					 | 
				
			||||||
            ? utils.createNotifierCallback()
 | 
					 | 
				
			||||||
            : undefined
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      resolve(devWebpackConfig)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
@@ -1,187 +0,0 @@
 | 
				
			|||||||
'use strict'
 | 
					 | 
				
			||||||
const path = require('path')
 | 
					 | 
				
			||||||
const utils = require('./utils')
 | 
					 | 
				
			||||||
const webpack = require('webpack')
 | 
					 | 
				
			||||||
const config = require('../config')
 | 
					 | 
				
			||||||
const merge = require('webpack-merge')
 | 
					 | 
				
			||||||
const baseWebpackConfig = require('./webpack.base.conf')
 | 
					 | 
				
			||||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
 | 
					 | 
				
			||||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
 | 
					 | 
				
			||||||
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')
 | 
					 | 
				
			||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
 | 
					 | 
				
			||||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
 | 
					 | 
				
			||||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function resolve(dir) {
 | 
					 | 
				
			||||||
  return path.join(__dirname, '..', dir)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const env = require('../config/' + process.env.env_config + '.env')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// For NamedChunksPlugin
 | 
					 | 
				
			||||||
const seen = new Set()
 | 
					 | 
				
			||||||
const nameLength = 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const webpackConfig = merge(baseWebpackConfig, {
 | 
					 | 
				
			||||||
  mode: 'production',
 | 
					 | 
				
			||||||
  module: {
 | 
					 | 
				
			||||||
    rules: utils.styleLoaders({
 | 
					 | 
				
			||||||
      sourceMap: config.build.productionSourceMap,
 | 
					 | 
				
			||||||
      extract: true,
 | 
					 | 
				
			||||||
      usePostCSS: true
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  devtool: config.build.productionSourceMap ? config.build.devtool : false,
 | 
					 | 
				
			||||||
  output: {
 | 
					 | 
				
			||||||
    path: config.build.assetsRoot,
 | 
					 | 
				
			||||||
    filename: utils.assetsPath('js/[name].[chunkhash:8].js'),
 | 
					 | 
				
			||||||
    chunkFilename: utils.assetsPath('js/[name].[chunkhash:8].js')
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  plugins: [
 | 
					 | 
				
			||||||
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
 | 
					 | 
				
			||||||
    new webpack.DefinePlugin({
 | 
					 | 
				
			||||||
      'process.env': env
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
    // extract css into its own file
 | 
					 | 
				
			||||||
    new MiniCssExtractPlugin({
 | 
					 | 
				
			||||||
      filename: utils.assetsPath('css/[name].[contenthash:8].css'),
 | 
					 | 
				
			||||||
      chunkFilename: utils.assetsPath('css/[name].[contenthash:8].css')
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
    // generate dist index.html with correct asset hash for caching.
 | 
					 | 
				
			||||||
    // you can customize output by editing /index.html
 | 
					 | 
				
			||||||
    // see https://github.com/ampedandwired/html-webpack-plugin
 | 
					 | 
				
			||||||
    new HtmlWebpackPlugin({
 | 
					 | 
				
			||||||
      filename: config.build.index,
 | 
					 | 
				
			||||||
      template: 'index.html',
 | 
					 | 
				
			||||||
      inject: true,
 | 
					 | 
				
			||||||
      favicon: resolve('favicon.ico'),
 | 
					 | 
				
			||||||
      title: 'vue-element-admin',
 | 
					 | 
				
			||||||
      templateParameters: {
 | 
					 | 
				
			||||||
        BASE_URL: config.build.assetsPublicPath + config.build.assetsSubDirectory,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      minify: {
 | 
					 | 
				
			||||||
        removeComments: true,
 | 
					 | 
				
			||||||
        collapseWhitespace: true,
 | 
					 | 
				
			||||||
        removeAttributeQuotes: true
 | 
					 | 
				
			||||||
        // more options:
 | 
					 | 
				
			||||||
        // https://github.com/kangax/html-minifier#options-quick-reference
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      // default sort mode uses toposort which cannot handle cyclic deps
 | 
					 | 
				
			||||||
      // in certain cases, and in webpack 4, chunk order in HTML doesn't
 | 
					 | 
				
			||||||
      // matter anyway
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
    new ScriptExtHtmlWebpackPlugin({
 | 
					 | 
				
			||||||
      //`runtime` must same as runtimeChunk name. default is `runtime`
 | 
					 | 
				
			||||||
      inline: /runtime\..*\.js$/
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
    // keep chunk.id stable when chunk has no name
 | 
					 | 
				
			||||||
    new webpack.NamedChunksPlugin(chunk => {
 | 
					 | 
				
			||||||
      if (chunk.name) {
 | 
					 | 
				
			||||||
        return chunk.name
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      const modules = Array.from(chunk.modulesIterable)
 | 
					 | 
				
			||||||
      if (modules.length > 1) {
 | 
					 | 
				
			||||||
        const hash = require('hash-sum')
 | 
					 | 
				
			||||||
        const joinedHash = hash(modules.map(m => m.id).join('_'))
 | 
					 | 
				
			||||||
        let len = nameLength
 | 
					 | 
				
			||||||
        while (seen.has(joinedHash.substr(0, len))) len++
 | 
					 | 
				
			||||||
        seen.add(joinedHash.substr(0, len))
 | 
					 | 
				
			||||||
        return `chunk-${joinedHash.substr(0, len)}`
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        return modules[0].id
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
    // keep module.id stable when vender modules does not change
 | 
					 | 
				
			||||||
    new webpack.HashedModuleIdsPlugin(),
 | 
					 | 
				
			||||||
    // copy custom static assets
 | 
					 | 
				
			||||||
    new CopyWebpackPlugin([
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        from: path.resolve(__dirname, '../static'),
 | 
					 | 
				
			||||||
        to: config.build.assetsSubDirectory,
 | 
					 | 
				
			||||||
        ignore: ['.*']
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ])
 | 
					 | 
				
			||||||
  ],
 | 
					 | 
				
			||||||
  optimization: {
 | 
					 | 
				
			||||||
    splitChunks: {
 | 
					 | 
				
			||||||
      chunks: 'all',
 | 
					 | 
				
			||||||
      cacheGroups: {
 | 
					 | 
				
			||||||
        libs: {
 | 
					 | 
				
			||||||
          name: 'chunk-libs',
 | 
					 | 
				
			||||||
          test: /[\\/]node_modules[\\/]/,
 | 
					 | 
				
			||||||
          priority: 10,
 | 
					 | 
				
			||||||
          chunks: 'initial' // 只打包初始时依赖的第三方
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        elementUI: {
 | 
					 | 
				
			||||||
          name: 'chunk-elementUI', // 单独将 elementUI 拆包
 | 
					 | 
				
			||||||
          priority: 20, // 权重要大于 libs 和 app 不然会被打包进 libs 或者 app
 | 
					 | 
				
			||||||
          test: /[\\/]node_modules[\\/]element-ui[\\/]/
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        commons: {
 | 
					 | 
				
			||||||
          name: 'chunk-commons',
 | 
					 | 
				
			||||||
          test: resolve('src/components'), // 可自定义拓展你的规则
 | 
					 | 
				
			||||||
          minChunks: 3, // 最小公用次数
 | 
					 | 
				
			||||||
          priority: 5,
 | 
					 | 
				
			||||||
          reuseExistingChunk: true
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    runtimeChunk: 'single',
 | 
					 | 
				
			||||||
    minimizer: [
 | 
					 | 
				
			||||||
      new UglifyJsPlugin({
 | 
					 | 
				
			||||||
        uglifyOptions: {
 | 
					 | 
				
			||||||
          mangle: {
 | 
					 | 
				
			||||||
            safari10: true
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        sourceMap: config.build.productionSourceMap,
 | 
					 | 
				
			||||||
        cache: true,
 | 
					 | 
				
			||||||
        parallel: true
 | 
					 | 
				
			||||||
      }),
 | 
					 | 
				
			||||||
      // Compress extracted CSS. We are using this plugin so that possible
 | 
					 | 
				
			||||||
      // duplicated CSS from different components can be deduped.
 | 
					 | 
				
			||||||
      new OptimizeCSSAssetsPlugin()
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if (config.build.productionGzip) {
 | 
					 | 
				
			||||||
  const CompressionWebpackPlugin = require('compression-webpack-plugin')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  webpackConfig.plugins.push(
 | 
					 | 
				
			||||||
    new CompressionWebpackPlugin({
 | 
					 | 
				
			||||||
      algorithm: 'gzip',
 | 
					 | 
				
			||||||
      test: new RegExp(
 | 
					 | 
				
			||||||
        '\\.(' + config.build.productionGzipExtensions.join('|') + ')$'
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      threshold: 10240,
 | 
					 | 
				
			||||||
      minRatio: 0.8
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
  )
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if (config.build.generateAnalyzerReport || config.build.bundleAnalyzerReport) {
 | 
					 | 
				
			||||||
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
 | 
					 | 
				
			||||||
    .BundleAnalyzerPlugin
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (config.build.bundleAnalyzerReport) {
 | 
					 | 
				
			||||||
    webpackConfig.plugins.push(
 | 
					 | 
				
			||||||
      new BundleAnalyzerPlugin({
 | 
					 | 
				
			||||||
        analyzerPort: 8080,
 | 
					 | 
				
			||||||
        generateStatsFile: false
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (config.build.generateAnalyzerReport) {
 | 
					 | 
				
			||||||
    webpackConfig.plugins.push(
 | 
					 | 
				
			||||||
      new BundleAnalyzerPlugin({
 | 
					 | 
				
			||||||
        analyzerMode: 'static',
 | 
					 | 
				
			||||||
        reportFilename: 'bundle-report.html',
 | 
					 | 
				
			||||||
        openAnalyzer: false
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = webpackConfig
 | 
					 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
  NODE_ENV: '"development"',
 | 
					 | 
				
			||||||
  ENV_CONFIG: '"dev"',
 | 
					 | 
				
			||||||
  BASE_API: '"https://api-dev"'
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,88 +0,0 @@
 | 
				
			|||||||
'use strict'
 | 
					 | 
				
			||||||
// Template version: 1.2.6
 | 
					 | 
				
			||||||
// see http://vuejs-templates.github.io/webpack for documentation.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const path = require('path')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
  dev: {
 | 
					 | 
				
			||||||
    // Paths
 | 
					 | 
				
			||||||
    assetsSubDirectory: 'static',
 | 
					 | 
				
			||||||
    assetsPublicPath: '/',
 | 
					 | 
				
			||||||
    proxyTable: {},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Various Dev Server settings
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // can be overwritten by process.env.HOST
 | 
					 | 
				
			||||||
    // if you want dev by ip, please set host: '0.0.0.0'
 | 
					 | 
				
			||||||
    host: 'localhost',
 | 
					 | 
				
			||||||
    port: 9527, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
 | 
					 | 
				
			||||||
    autoOpenBrowser: true,
 | 
					 | 
				
			||||||
    errorOverlay: true,
 | 
					 | 
				
			||||||
    notifyOnErrors: false,
 | 
					 | 
				
			||||||
    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Use Eslint Loader?
 | 
					 | 
				
			||||||
    // If true, your code will be linted during bundling and
 | 
					 | 
				
			||||||
    // linting errors and warnings will be shown in the console.
 | 
					 | 
				
			||||||
    useEslint: true,
 | 
					 | 
				
			||||||
    // If true, eslint errors and warnings will also be shown in the error overlay
 | 
					 | 
				
			||||||
    // in the browser.
 | 
					 | 
				
			||||||
    showEslintErrorsInOverlay: false,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Source Maps
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // https://webpack.js.org/configuration/devtool/#development
 | 
					 | 
				
			||||||
    devtool: 'cheap-source-map',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // CSS Sourcemaps off by default because relative paths are "buggy"
 | 
					 | 
				
			||||||
    // with this option, according to the CSS-Loader README
 | 
					 | 
				
			||||||
    // (https://github.com/webpack/css-loader#sourcemaps)
 | 
					 | 
				
			||||||
    // In our experience, they generally work as expected,
 | 
					 | 
				
			||||||
    // just be aware of this issue when enabling this option.
 | 
					 | 
				
			||||||
    cssSourceMap: false
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  build: {
 | 
					 | 
				
			||||||
    // Template for index.html
 | 
					 | 
				
			||||||
    index: path.resolve(__dirname, '../dist/index.html'),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Paths
 | 
					 | 
				
			||||||
    assetsRoot: path.resolve(__dirname, '../dist'),
 | 
					 | 
				
			||||||
    assetsSubDirectory: 'static',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * You can set by youself according to actual condition
 | 
					 | 
				
			||||||
     * You will need to set this if you plan to deploy your site under a sub path,
 | 
					 | 
				
			||||||
     * for example GitHub pages. If you plan to deploy your site to https://foo.github.io/bar/,
 | 
					 | 
				
			||||||
     * then assetsPublicPath should be set to "/bar/".
 | 
					 | 
				
			||||||
     * In most cases please use '/' !!!
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    assetsPublicPath: '/',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Source Maps
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    productionSourceMap: false,
 | 
					 | 
				
			||||||
    // https://webpack.js.org/configuration/devtool/#production
 | 
					 | 
				
			||||||
    devtool: 'source-map',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Gzip off by default as many popular static hosts such as
 | 
					 | 
				
			||||||
    // Surge or Netlify already gzip all static assets for you.
 | 
					 | 
				
			||||||
    // Before setting to `true`, make sure to:
 | 
					 | 
				
			||||||
    // npm install --save-dev compression-webpack-plugin
 | 
					 | 
				
			||||||
    productionGzip: false,
 | 
					 | 
				
			||||||
    productionGzipExtensions: ['js', 'css'],
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Run the build command with an extra argument to
 | 
					 | 
				
			||||||
    // View the bundle analyzer report after build finishes:
 | 
					 | 
				
			||||||
    // `npm run build:prod --report`
 | 
					 | 
				
			||||||
    // Set to `true` or `false` to always turn it on or off
 | 
					 | 
				
			||||||
    bundleAnalyzerReport: process.env.npm_config_report || false,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // `npm run build:prod --generate_report`
 | 
					 | 
				
			||||||
    generateAnalyzerReport: process.env.npm_config_generate_report || false
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
  NODE_ENV: '"production"',
 | 
					 | 
				
			||||||
  ENV_CONFIG: '"prod"',
 | 
					 | 
				
			||||||
  BASE_API: '"https://api-prod"'
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
  NODE_ENV: '"production"',
 | 
					 | 
				
			||||||
  ENV_CONFIG: '"sit"',
 | 
					 | 
				
			||||||
  BASE_API: '"https://api-sit"'
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										27
									
								
								jest.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					  verbose: true,
 | 
				
			||||||
 | 
					  moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
 | 
				
			||||||
 | 
					  transformIgnorePatterns: [
 | 
				
			||||||
 | 
					    'node_modules/(?!(babel-jest|jest-vue-preprocessor)/)'
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  transform: {
 | 
				
			||||||
 | 
					    '^.+\\.vue$': 'vue-jest',
 | 
				
			||||||
 | 
					    '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
 | 
				
			||||||
 | 
					    '^.+\\.jsx?$': 'babel-jest'
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  moduleNameMapper: {
 | 
				
			||||||
 | 
					    '^@/(.*)$': '<rootDir>/src/$1'
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  snapshotSerializers: ['jest-serializer-vue'],
 | 
				
			||||||
 | 
					  testMatch: [
 | 
				
			||||||
 | 
					    '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
 | 
				
			||||||
 | 
					  coverageDirectory: '<rootDir>/tests/unit/coverage',
 | 
				
			||||||
 | 
					  // 'collectCoverage': true,
 | 
				
			||||||
 | 
					  'coverageReporters': [
 | 
				
			||||||
 | 
					    'lcov',
 | 
				
			||||||
 | 
					    'text-summary'
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  testURL: 'http://localhost/'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										116
									
								
								mock/article.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,116 @@
 | 
				
			|||||||
 | 
					import Mock from 'mockjs'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const List = []
 | 
				
			||||||
 | 
					const count = 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const baseContent = '<p>我是测试数据我是测试数据</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>'
 | 
				
			||||||
 | 
					const image_uri = 'https://wpimg.wallstcn.com/e4558086-631c-425c-9430-56ffb46e70b3'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for (let i = 0; i < count; i++) {
 | 
				
			||||||
 | 
					  List.push(Mock.mock({
 | 
				
			||||||
 | 
					    id: '@increment',
 | 
				
			||||||
 | 
					    timestamp: +Mock.Random.date('T'),
 | 
				
			||||||
 | 
					    author: '@first',
 | 
				
			||||||
 | 
					    reviewer: '@first',
 | 
				
			||||||
 | 
					    title: '@title(5, 10)',
 | 
				
			||||||
 | 
					    content_short: 'mock data',
 | 
				
			||||||
 | 
					    content: baseContent,
 | 
				
			||||||
 | 
					    forecast: '@float(0, 100, 2, 2)',
 | 
				
			||||||
 | 
					    importance: '@integer(1, 3)',
 | 
				
			||||||
 | 
					    'type|1': ['CN', 'US', 'JP', 'EU'],
 | 
				
			||||||
 | 
					    'status|1': ['published', 'draft', 'deleted'],
 | 
				
			||||||
 | 
					    display_time: '@datetime',
 | 
				
			||||||
 | 
					    comment_disabled: true,
 | 
				
			||||||
 | 
					    pageviews: '@integer(300, 5000)',
 | 
				
			||||||
 | 
					    image_uri,
 | 
				
			||||||
 | 
					    platforms: ['a-platform']
 | 
				
			||||||
 | 
					  }))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default [
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/article/list',
 | 
				
			||||||
 | 
					    type: 'get',
 | 
				
			||||||
 | 
					    response: config => {
 | 
				
			||||||
 | 
					      const { importance, type, title, page = 1, limit = 20, sort } = config.query
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      let mockList = List.filter(item => {
 | 
				
			||||||
 | 
					        if (importance && item.importance !== +importance) return false
 | 
				
			||||||
 | 
					        if (type && item.type !== type) return false
 | 
				
			||||||
 | 
					        if (title && item.title.indexOf(title) < 0) return false
 | 
				
			||||||
 | 
					        return true
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (sort === '-id') {
 | 
				
			||||||
 | 
					        mockList = mockList.reverse()
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        code: 20000,
 | 
				
			||||||
 | 
					        data: {
 | 
				
			||||||
 | 
					          total: mockList.length,
 | 
				
			||||||
 | 
					          items: pageList
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/article/detail',
 | 
				
			||||||
 | 
					    type: 'get',
 | 
				
			||||||
 | 
					    response: config => {
 | 
				
			||||||
 | 
					      const { id } = config.query
 | 
				
			||||||
 | 
					      for (const article of List) {
 | 
				
			||||||
 | 
					        if (article.id === +id) {
 | 
				
			||||||
 | 
					          return {
 | 
				
			||||||
 | 
					            code: 20000,
 | 
				
			||||||
 | 
					            data: article
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/article/pv',
 | 
				
			||||||
 | 
					    type: 'get',
 | 
				
			||||||
 | 
					    response: _ => {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        code: 20000,
 | 
				
			||||||
 | 
					        data: {
 | 
				
			||||||
 | 
					          pvData: [
 | 
				
			||||||
 | 
					            { key: 'PC', pv: 1024 },
 | 
				
			||||||
 | 
					            { key: 'mobile', pv: 1024 },
 | 
				
			||||||
 | 
					            { key: 'ios', pv: 1024 },
 | 
				
			||||||
 | 
					            { key: 'android', pv: 1024 }
 | 
				
			||||||
 | 
					          ]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/article/create',
 | 
				
			||||||
 | 
					    type: 'post',
 | 
				
			||||||
 | 
					    response: _ => {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        code: 20000,
 | 
				
			||||||
 | 
					        data: 'success'
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/article/update',
 | 
				
			||||||
 | 
					    type: 'post',
 | 
				
			||||||
 | 
					    response: _ => {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        code: 20000,
 | 
				
			||||||
 | 
					        data: 'success'
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										57
									
								
								mock/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					import Mock from 'mockjs'
 | 
				
			||||||
 | 
					import mocks from './mocks'
 | 
				
			||||||
 | 
					import { param2Obj } from '../src/utils'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const MOCK_API_BASE = '/mock'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function mockXHR() {
 | 
				
			||||||
 | 
					  // 修复在使用 MockJS 情况下,设置 withCredentials = true,且未被拦截的跨域请求丢失 Cookies 的问题
 | 
				
			||||||
 | 
					  // https://github.com/nuysoft/Mock/issues/300
 | 
				
			||||||
 | 
					  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
 | 
				
			||||||
 | 
					        // https://expressjs.com/en/4x/api.html#req
 | 
				
			||||||
 | 
					        result = respond({
 | 
				
			||||||
 | 
					          method: type,
 | 
				
			||||||
 | 
					          body: JSON.parse(body),
 | 
				
			||||||
 | 
					          query: param2Obj(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))
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const responseFake = (url, type, respond) => {
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    url: new RegExp(`${MOCK_API_BASE}${url}`),
 | 
				
			||||||
 | 
					    type: type || 'get',
 | 
				
			||||||
 | 
					    response(req, res) {
 | 
				
			||||||
 | 
					      res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default mocks.map(route => {
 | 
				
			||||||
 | 
					  return responseFake(route.url, route.type, route.response)
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
							
								
								
									
										12
									
								
								mock/mocks.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import user from './user'
 | 
				
			||||||
 | 
					import role from './role'
 | 
				
			||||||
 | 
					import article from './article'
 | 
				
			||||||
 | 
					import search from './remoteSearch'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default [
 | 
				
			||||||
 | 
					  ...user,
 | 
				
			||||||
 | 
					  ...role,
 | 
				
			||||||
 | 
					  ...article,
 | 
				
			||||||
 | 
					  ...search
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										51
									
								
								mock/remoteSearch.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					import Mock from 'mockjs'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const NameList = []
 | 
				
			||||||
 | 
					const count = 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for (let i = 0; i < count; i++) {
 | 
				
			||||||
 | 
					  NameList.push(Mock.mock({
 | 
				
			||||||
 | 
					    name: '@first'
 | 
				
			||||||
 | 
					  }))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					NameList.push({ name: 'mock-Pan' })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default [
 | 
				
			||||||
 | 
					  // username search
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/search/user',
 | 
				
			||||||
 | 
					    type: 'get',
 | 
				
			||||||
 | 
					    response: config => {
 | 
				
			||||||
 | 
					      const { name } = config.query
 | 
				
			||||||
 | 
					      const mockNameList = NameList.filter(item => {
 | 
				
			||||||
 | 
					        const lowerCaseName = item.name.toLowerCase()
 | 
				
			||||||
 | 
					        return !(name && lowerCaseName.indexOf(name.toLowerCase()) < 0)
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        code: 20000,
 | 
				
			||||||
 | 
					        data: { items: mockNameList }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // transaction list
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/transaction/list',
 | 
				
			||||||
 | 
					    type: 'get',
 | 
				
			||||||
 | 
					    response: _ => {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        code: 20000,
 | 
				
			||||||
 | 
					        data: {
 | 
				
			||||||
 | 
					          total: 20,
 | 
				
			||||||
 | 
					          'items|20': [{
 | 
				
			||||||
 | 
					            order_no: '@guid()',
 | 
				
			||||||
 | 
					            timestamp: +Mock.Random.date('T'),
 | 
				
			||||||
 | 
					            username: '@name()',
 | 
				
			||||||
 | 
					            price: '@float(1000, 15000, 0, 2)',
 | 
				
			||||||
 | 
					            'status|1': ['success', 'pending']
 | 
				
			||||||
 | 
					          }]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
							
								
								
									
										98
									
								
								mock/role/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,98 @@
 | 
				
			|||||||
 | 
					import Mock from 'mockjs'
 | 
				
			||||||
 | 
					import { deepClone } from '../../src/utils/index.js'
 | 
				
			||||||
 | 
					import { asyncRoutes, constantRoutes } from './routes.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const routes = deepClone([...constantRoutes, ...asyncRoutes])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const roles = [
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    key: 'admin',
 | 
				
			||||||
 | 
					    name: 'admin',
 | 
				
			||||||
 | 
					    description: 'Super Administrator. Have access to view all pages.',
 | 
				
			||||||
 | 
					    routes: routes
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    key: 'editor',
 | 
				
			||||||
 | 
					    name: 'editor',
 | 
				
			||||||
 | 
					    description: 'Normal Editor. Can see all pages except permission page',
 | 
				
			||||||
 | 
					    routes: routes.filter(i => i.path !== '/permission')// just a mock
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    key: 'visitor',
 | 
				
			||||||
 | 
					    name: 'visitor',
 | 
				
			||||||
 | 
					    description: 'Just a visitor. Can only see the home page and the document page',
 | 
				
			||||||
 | 
					    routes: [{
 | 
				
			||||||
 | 
					      path: '',
 | 
				
			||||||
 | 
					      redirect: 'dashboard',
 | 
				
			||||||
 | 
					      children: [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          path: 'dashboard',
 | 
				
			||||||
 | 
					          name: 'Dashboard',
 | 
				
			||||||
 | 
					          meta: { title: 'dashboard', icon: 'dashboard' }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    }]
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default [
 | 
				
			||||||
 | 
					  // mock get all routes form server
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/routes',
 | 
				
			||||||
 | 
					    type: 'get',
 | 
				
			||||||
 | 
					    response: _ => {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        code: 20000,
 | 
				
			||||||
 | 
					        data: routes
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // mock get all roles form server
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/roles',
 | 
				
			||||||
 | 
					    type: 'get',
 | 
				
			||||||
 | 
					    response: _ => {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        code: 20000,
 | 
				
			||||||
 | 
					        data: roles
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // add role
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/role',
 | 
				
			||||||
 | 
					    type: 'post',
 | 
				
			||||||
 | 
					    response: {
 | 
				
			||||||
 | 
					      code: 20000,
 | 
				
			||||||
 | 
					      data: {
 | 
				
			||||||
 | 
					        key: Mock.mock('@integer(300, 5000)')
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // update role
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/role/[A-Za-z0-9]',
 | 
				
			||||||
 | 
					    type: 'put',
 | 
				
			||||||
 | 
					    response: {
 | 
				
			||||||
 | 
					      code: 20000,
 | 
				
			||||||
 | 
					      data: {
 | 
				
			||||||
 | 
					        status: 'success'
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // delete role
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/role/[A-Za-z0-9]',
 | 
				
			||||||
 | 
					    type: 'delete',
 | 
				
			||||||
 | 
					    response: {
 | 
				
			||||||
 | 
					      code: 20000,
 | 
				
			||||||
 | 
					      data: {
 | 
				
			||||||
 | 
					        status: 'success'
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
							
								
								
									
										525
									
								
								mock/role/routes.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,525 @@
 | 
				
			|||||||
 | 
					// Just a mock data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const constantRoutes = [
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/redirect',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    hidden: true,
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: '/redirect/:path*',
 | 
				
			||||||
 | 
					        component: 'views/redirect/index'
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/login',
 | 
				
			||||||
 | 
					    component: 'views/login/index',
 | 
				
			||||||
 | 
					    hidden: true
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/auth-redirect',
 | 
				
			||||||
 | 
					    component: 'views/login/authredirect',
 | 
				
			||||||
 | 
					    hidden: true
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/404',
 | 
				
			||||||
 | 
					    component: 'views/errorPage/404',
 | 
				
			||||||
 | 
					    hidden: true
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/401',
 | 
				
			||||||
 | 
					    component: 'views/errorPage/401',
 | 
				
			||||||
 | 
					    hidden: true
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: 'dashboard',
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'dashboard',
 | 
				
			||||||
 | 
					        component: 'views/dashboard/index',
 | 
				
			||||||
 | 
					        name: 'Dashboard',
 | 
				
			||||||
 | 
					        meta: { title: 'dashboard', icon: 'dashboard', noCache: true, affix: true }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/documentation',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'index',
 | 
				
			||||||
 | 
					        component: 'views/documentation/index',
 | 
				
			||||||
 | 
					        name: 'Documentation',
 | 
				
			||||||
 | 
					        meta: { title: 'documentation', icon: 'documentation', affix: true }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/guide',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: '/guide/index',
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'index',
 | 
				
			||||||
 | 
					        component: 'views/guide/index',
 | 
				
			||||||
 | 
					        name: 'Guide',
 | 
				
			||||||
 | 
					        meta: { title: 'guide', icon: 'guide', noCache: true }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const asyncRoutes = [
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/permission',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: '/permission/index',
 | 
				
			||||||
 | 
					    alwaysShow: true,
 | 
				
			||||||
 | 
					    meta: {
 | 
				
			||||||
 | 
					      title: 'permission',
 | 
				
			||||||
 | 
					      icon: 'lock',
 | 
				
			||||||
 | 
					      roles: ['admin', 'editor']
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'page',
 | 
				
			||||||
 | 
					        component: 'views/permission/page',
 | 
				
			||||||
 | 
					        name: 'PagePermission',
 | 
				
			||||||
 | 
					        meta: {
 | 
				
			||||||
 | 
					          title: 'pagePermission',
 | 
				
			||||||
 | 
					          roles: ['admin']
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'directive',
 | 
				
			||||||
 | 
					        component: 'views/permission/directive',
 | 
				
			||||||
 | 
					        name: 'DirectivePermission',
 | 
				
			||||||
 | 
					        meta: {
 | 
				
			||||||
 | 
					          title: 'directivePermission'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'role',
 | 
				
			||||||
 | 
					        component: 'views/permission/role',
 | 
				
			||||||
 | 
					        name: 'RolePermission',
 | 
				
			||||||
 | 
					        meta: {
 | 
				
			||||||
 | 
					          title: 'rolePermission',
 | 
				
			||||||
 | 
					          roles: ['admin']
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/icon',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'index',
 | 
				
			||||||
 | 
					        component: 'views/svg-icons/index',
 | 
				
			||||||
 | 
					        name: 'Icons',
 | 
				
			||||||
 | 
					        meta: { title: 'icons', icon: 'icon', noCache: true }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/components',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: 'noredirect',
 | 
				
			||||||
 | 
					    name: 'ComponentDemo',
 | 
				
			||||||
 | 
					    meta: {
 | 
				
			||||||
 | 
					      title: 'components',
 | 
				
			||||||
 | 
					      icon: 'component'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'tinymce',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/tinymce',
 | 
				
			||||||
 | 
					        name: 'TinymceDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'tinymce' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'markdown',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/markdown',
 | 
				
			||||||
 | 
					        name: 'MarkdownDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'markdown' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'json-editor',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/jsonEditor',
 | 
				
			||||||
 | 
					        name: 'JsonEditorDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'jsonEditor' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'splitpane',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/splitpane',
 | 
				
			||||||
 | 
					        name: 'SplitpaneDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'splitPane' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'avatar-upload',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/avatarUpload',
 | 
				
			||||||
 | 
					        name: 'AvatarUploadDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'avatarUpload' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'dropzone',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/dropzone',
 | 
				
			||||||
 | 
					        name: 'DropzoneDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'dropzone' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'sticky',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/sticky',
 | 
				
			||||||
 | 
					        name: 'StickyDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'sticky' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'count-to',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/countTo',
 | 
				
			||||||
 | 
					        name: 'CountToDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'countTo' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'mixin',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/mixin',
 | 
				
			||||||
 | 
					        name: 'ComponentMixinDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'componentMixin' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'back-to-top',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/backToTop',
 | 
				
			||||||
 | 
					        name: 'BackToTopDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'backToTop' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'drag-dialog',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/dragDialog',
 | 
				
			||||||
 | 
					        name: 'DragDialogDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'dragDialog' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'drag-select',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/dragSelect',
 | 
				
			||||||
 | 
					        name: 'DragSelectDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'dragSelect' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'dnd-list',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/dndList',
 | 
				
			||||||
 | 
					        name: 'DndListDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'dndList' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'drag-kanban',
 | 
				
			||||||
 | 
					        component: 'views/components-demo/dragKanban',
 | 
				
			||||||
 | 
					        name: 'DragKanbanDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'dragKanban' }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/charts',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: 'noredirect',
 | 
				
			||||||
 | 
					    name: 'Charts',
 | 
				
			||||||
 | 
					    meta: {
 | 
				
			||||||
 | 
					      title: 'charts',
 | 
				
			||||||
 | 
					      icon: 'chart'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'keyboard',
 | 
				
			||||||
 | 
					        component: 'views/charts/keyboard',
 | 
				
			||||||
 | 
					        name: 'KeyboardChart',
 | 
				
			||||||
 | 
					        meta: { title: 'keyboardChart', noCache: true }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'line',
 | 
				
			||||||
 | 
					        component: 'views/charts/line',
 | 
				
			||||||
 | 
					        name: 'LineChart',
 | 
				
			||||||
 | 
					        meta: { title: 'lineChart', noCache: true }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'mixchart',
 | 
				
			||||||
 | 
					        component: 'views/charts/mixChart',
 | 
				
			||||||
 | 
					        name: 'MixChart',
 | 
				
			||||||
 | 
					        meta: { title: 'mixChart', noCache: true }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/nested',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: '/nested/menu1/menu1-1',
 | 
				
			||||||
 | 
					    name: 'Nested',
 | 
				
			||||||
 | 
					    meta: {
 | 
				
			||||||
 | 
					      title: 'nested',
 | 
				
			||||||
 | 
					      icon: 'nested'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'menu1',
 | 
				
			||||||
 | 
					        component: 'views/nested/menu1/index',
 | 
				
			||||||
 | 
					        name: 'Menu1',
 | 
				
			||||||
 | 
					        meta: { title: 'menu1' },
 | 
				
			||||||
 | 
					        redirect: '/nested/menu1/menu1-1',
 | 
				
			||||||
 | 
					        children: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            path: 'menu1-1',
 | 
				
			||||||
 | 
					            component: 'views/nested/menu1/menu1-1',
 | 
				
			||||||
 | 
					            name: 'Menu1-1',
 | 
				
			||||||
 | 
					            meta: { title: 'menu1-1' }
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            path: 'menu1-2',
 | 
				
			||||||
 | 
					            component: 'views/nested/menu1/menu1-2',
 | 
				
			||||||
 | 
					            name: 'Menu1-2',
 | 
				
			||||||
 | 
					            redirect: '/nested/menu1/menu1-2/menu1-2-1',
 | 
				
			||||||
 | 
					            meta: { title: 'menu1-2' },
 | 
				
			||||||
 | 
					            children: [
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                path: 'menu1-2-1',
 | 
				
			||||||
 | 
					                component: 'views/nested/menu1/menu1-2/menu1-2-1',
 | 
				
			||||||
 | 
					                name: 'Menu1-2-1',
 | 
				
			||||||
 | 
					                meta: { title: 'menu1-2-1' }
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                path: 'menu1-2-2',
 | 
				
			||||||
 | 
					                component: 'views/nested/menu1/menu1-2/menu1-2-2',
 | 
				
			||||||
 | 
					                name: 'Menu1-2-2',
 | 
				
			||||||
 | 
					                meta: { title: 'menu1-2-2' }
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            path: 'menu1-3',
 | 
				
			||||||
 | 
					            component: 'views/nested/menu1/menu1-3',
 | 
				
			||||||
 | 
					            name: 'Menu1-3',
 | 
				
			||||||
 | 
					            meta: { title: 'menu1-3' }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'menu2',
 | 
				
			||||||
 | 
					        name: 'Menu2',
 | 
				
			||||||
 | 
					        component: 'views/nested/menu2/index',
 | 
				
			||||||
 | 
					        meta: { title: 'menu2' }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/example',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: '/example/list',
 | 
				
			||||||
 | 
					    name: 'Example',
 | 
				
			||||||
 | 
					    meta: {
 | 
				
			||||||
 | 
					      title: 'example',
 | 
				
			||||||
 | 
					      icon: 'example'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'create',
 | 
				
			||||||
 | 
					        component: 'views/example/create',
 | 
				
			||||||
 | 
					        name: 'CreateArticle',
 | 
				
			||||||
 | 
					        meta: { title: 'createArticle', icon: 'edit' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'edit/:id(\\d+)',
 | 
				
			||||||
 | 
					        component: 'views/example/edit',
 | 
				
			||||||
 | 
					        name: 'EditArticle',
 | 
				
			||||||
 | 
					        meta: { title: 'editArticle', noCache: true },
 | 
				
			||||||
 | 
					        hidden: true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'list',
 | 
				
			||||||
 | 
					        component: 'views/example/list',
 | 
				
			||||||
 | 
					        name: 'ArticleList',
 | 
				
			||||||
 | 
					        meta: { title: 'articleList', icon: 'list' }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/tab',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'index',
 | 
				
			||||||
 | 
					        component: 'views/tab/index',
 | 
				
			||||||
 | 
					        name: 'Tab',
 | 
				
			||||||
 | 
					        meta: { title: 'tab', icon: 'tab' }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/error',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: 'noredirect',
 | 
				
			||||||
 | 
					    name: 'ErrorPages',
 | 
				
			||||||
 | 
					    meta: {
 | 
				
			||||||
 | 
					      title: 'errorPages',
 | 
				
			||||||
 | 
					      icon: '404'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: '401',
 | 
				
			||||||
 | 
					        component: 'views/errorPage/401',
 | 
				
			||||||
 | 
					        name: 'Page401',
 | 
				
			||||||
 | 
					        meta: { title: 'page401', noCache: true }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: '404',
 | 
				
			||||||
 | 
					        component: 'views/errorPage/404',
 | 
				
			||||||
 | 
					        name: 'Page404',
 | 
				
			||||||
 | 
					        meta: { title: 'page404', noCache: true }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/error-log',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: 'noredirect',
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'log',
 | 
				
			||||||
 | 
					        component: 'views/errorLog/index',
 | 
				
			||||||
 | 
					        name: 'ErrorLog',
 | 
				
			||||||
 | 
					        meta: { title: 'errorLog', icon: 'bug' }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/excel',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: '/excel/export-excel',
 | 
				
			||||||
 | 
					    name: 'Excel',
 | 
				
			||||||
 | 
					    meta: {
 | 
				
			||||||
 | 
					      title: 'excel',
 | 
				
			||||||
 | 
					      icon: 'excel'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'export-excel',
 | 
				
			||||||
 | 
					        component: 'views/excel/exportExcel',
 | 
				
			||||||
 | 
					        name: 'ExportExcel',
 | 
				
			||||||
 | 
					        meta: { title: 'exportExcel' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'export-selected-excel',
 | 
				
			||||||
 | 
					        component: 'views/excel/selectExcel',
 | 
				
			||||||
 | 
					        name: 'SelectExcel',
 | 
				
			||||||
 | 
					        meta: { title: 'selectExcel' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'export-merge-header',
 | 
				
			||||||
 | 
					        component: 'views/excel/mergeHeader',
 | 
				
			||||||
 | 
					        name: 'MergeHeader',
 | 
				
			||||||
 | 
					        meta: { title: 'mergeHeader' }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'upload-excel',
 | 
				
			||||||
 | 
					        component: 'views/excel/uploadExcel',
 | 
				
			||||||
 | 
					        name: 'UploadExcel',
 | 
				
			||||||
 | 
					        meta: { title: 'uploadExcel' }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/zip',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: '/zip/download',
 | 
				
			||||||
 | 
					    alwaysShow: true,
 | 
				
			||||||
 | 
					    meta: { title: 'zip', icon: 'zip' },
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'download',
 | 
				
			||||||
 | 
					        component: 'views/zip/index',
 | 
				
			||||||
 | 
					        name: 'ExportZip',
 | 
				
			||||||
 | 
					        meta: { title: 'exportZip' }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/pdf',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: '/pdf/index',
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'index',
 | 
				
			||||||
 | 
					        component: 'views/pdf/index',
 | 
				
			||||||
 | 
					        name: 'PDF',
 | 
				
			||||||
 | 
					        meta: { title: 'pdf', icon: 'pdf' }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/pdf/download',
 | 
				
			||||||
 | 
					    component: 'views/pdf/download',
 | 
				
			||||||
 | 
					    hidden: true
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/theme',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: 'noredirect',
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'index',
 | 
				
			||||||
 | 
					        component: 'views/theme/index',
 | 
				
			||||||
 | 
					        name: 'Theme',
 | 
				
			||||||
 | 
					        meta: { title: 'theme', icon: 'theme' }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/clipboard',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    redirect: 'noredirect',
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'index',
 | 
				
			||||||
 | 
					        component: 'views/clipboard/index',
 | 
				
			||||||
 | 
					        name: 'ClipboardDemo',
 | 
				
			||||||
 | 
					        meta: { title: 'clipboardDemo', icon: 'clipboard' }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: '/i18n',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'index',
 | 
				
			||||||
 | 
					        component: 'views/i18n-demo/index',
 | 
				
			||||||
 | 
					        name: 'I18n',
 | 
				
			||||||
 | 
					        meta: { title: 'i18n', icon: 'international' }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    path: 'external-link',
 | 
				
			||||||
 | 
					    component: 'layout/Layout',
 | 
				
			||||||
 | 
					    children: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        path: 'https://github.com/PanJiaChen/vue-element-admin',
 | 
				
			||||||
 | 
					        meta: { title: 'externalLink', icon: 'link' }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { path: '*', redirect: '/404', hidden: true }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
							
								
								
									
										84
									
								
								mock/user.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					const tokens = {
 | 
				
			||||||
 | 
					  admin: {
 | 
				
			||||||
 | 
					    token: 'admin-token'
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  editor: {
 | 
				
			||||||
 | 
					    token: 'editor-token'
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const users = {
 | 
				
			||||||
 | 
					  'admin-token': {
 | 
				
			||||||
 | 
					    roles: ['admin'],
 | 
				
			||||||
 | 
					    introduction: 'I am a super administrator',
 | 
				
			||||||
 | 
					    avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
 | 
				
			||||||
 | 
					    name: 'Super Admin'
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  'editor-token': {
 | 
				
			||||||
 | 
					    roles: ['editor'],
 | 
				
			||||||
 | 
					    introduction: 'I am an editor',
 | 
				
			||||||
 | 
					    avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
 | 
				
			||||||
 | 
					    name: 'Normal Editor'
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default [
 | 
				
			||||||
 | 
					  // user login
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/user/login',
 | 
				
			||||||
 | 
					    type: 'post',
 | 
				
			||||||
 | 
					    response: config => {
 | 
				
			||||||
 | 
					      const { username } = config.body
 | 
				
			||||||
 | 
					      const token = tokens[username]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // mock error
 | 
				
			||||||
 | 
					      if (!token) {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          code: 60204,
 | 
				
			||||||
 | 
					          message: 'Account and password are incorrect.'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        code: 20000,
 | 
				
			||||||
 | 
					        data: token
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // get user info
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/user/info\.*',
 | 
				
			||||||
 | 
					    type: 'get',
 | 
				
			||||||
 | 
					    response: config => {
 | 
				
			||||||
 | 
					      const { token } = config.query
 | 
				
			||||||
 | 
					      const info = users[token]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // mock error
 | 
				
			||||||
 | 
					      if (!info) {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          code: 50008,
 | 
				
			||||||
 | 
					          message: 'Login failed, unable to get user details.'
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        code: 20000,
 | 
				
			||||||
 | 
					        data: info
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // user logout
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    url: '/user/logout',
 | 
				
			||||||
 | 
					    type: 'post',
 | 
				
			||||||
 | 
					    response: _ => {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        code: 20000,
 | 
				
			||||||
 | 
					        data: 'success'
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
							
								
								
									
										150
									
								
								package.json
									
									
									
									
									
								
							
							
						
						@@ -1,17 +1,24 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "vue-element-admin",
 | 
					  "name": "vue-element-admin",
 | 
				
			||||||
  "version": "3.10.0",
 | 
					  "version": "4.0.0",
 | 
				
			||||||
  "description": "A magical vue admin. Typical templates for enterprise applications. Newest development stack of vue. Lots of awesome features",
 | 
					  "description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features",
 | 
				
			||||||
  "author": "Pan <panfree23@gmail.com>",
 | 
					  "author": "Pan <panfree23@gmail.com>",
 | 
				
			||||||
  "license": "MIT",
 | 
					  "license": "MIT",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "dev": "cross-env BABEL_ENV=development webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
 | 
					    "dev": "vue-cli-service serve",
 | 
				
			||||||
    "build:prod": "cross-env NODE_ENV=production env_config=prod node build/build.js",
 | 
					    "build:prod": "vue-cli-service build",
 | 
				
			||||||
    "build:sit": "cross-env NODE_ENV=production env_config=sit node build/build.js",
 | 
					    "build:stage": "vue-cli-service build --mode staging",
 | 
				
			||||||
 | 
					    "preview": "node build/index.js --preview",
 | 
				
			||||||
    "lint": "eslint --ext .js,.vue src",
 | 
					    "lint": "eslint --ext .js,.vue src",
 | 
				
			||||||
    "test": "npm run lint",
 | 
					    "test:unit": "vue-cli-service test:unit",
 | 
				
			||||||
    "precommit": "lint-staged",
 | 
					    "test:ci": "npm run lint && npm run test:unit",
 | 
				
			||||||
    "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
 | 
					    "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
 | 
				
			||||||
 | 
					    "new": "plop"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "husky": {
 | 
				
			||||||
 | 
					    "hooks": {
 | 
				
			||||||
 | 
					      "pre-commit": "lint-staged"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "lint-staged": {
 | 
					  "lint-staged": {
 | 
				
			||||||
    "src/**/*.{js,vue}": [
 | 
					    "src/**/*.{js,vue}": [
 | 
				
			||||||
@@ -21,10 +28,12 @@
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  "keywords": [
 | 
					  "keywords": [
 | 
				
			||||||
    "vue",
 | 
					    "vue",
 | 
				
			||||||
    "element-ui",
 | 
					 | 
				
			||||||
    "admin",
 | 
					    "admin",
 | 
				
			||||||
    "management-system",
 | 
					    "dashboard",
 | 
				
			||||||
    "admin-template"
 | 
					    "element-ui",
 | 
				
			||||||
 | 
					    "boilerplate",
 | 
				
			||||||
 | 
					    "admin-template",
 | 
				
			||||||
 | 
					    "management-system"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "repository": {
 | 
					  "repository": {
 | 
				
			||||||
    "type": "git",
 | 
					    "type": "git",
 | 
				
			||||||
@@ -35,93 +44,64 @@
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "axios": "0.18.0",
 | 
					    "axios": "0.18.0",
 | 
				
			||||||
    "clipboard": "1.7.1",
 | 
					    "clipboard": "2.0.4",
 | 
				
			||||||
    "codemirror": "5.39.2",
 | 
					    "codemirror": "5.45.0",
 | 
				
			||||||
    "driver.js": "0.8.1",
 | 
					    "driver.js": "0.9.5",
 | 
				
			||||||
    "dropzone": "5.2.0",
 | 
					    "dropzone": "5.5.1",
 | 
				
			||||||
    "echarts": "4.1.0",
 | 
					    "echarts": "4.2.1",
 | 
				
			||||||
    "element-ui": "2.4.11",
 | 
					    "element-ui": "2.7.0",
 | 
				
			||||||
    "file-saver": "1.3.8",
 | 
					    "file-saver": "2.0.1",
 | 
				
			||||||
    "fuse.js": "3.4.2",
 | 
					    "fuse.js": "3.4.4",
 | 
				
			||||||
    "js-cookie": "2.2.0",
 | 
					    "js-cookie": "2.2.0",
 | 
				
			||||||
    "jsonlint": "1.6.3",
 | 
					    "jsonlint": "1.6.3",
 | 
				
			||||||
    "jszip": "3.1.5",
 | 
					    "jszip": "3.2.1",
 | 
				
			||||||
    "mockjs": "1.0.1-beta3",
 | 
					 | 
				
			||||||
    "normalize.css": "7.0.0",
 | 
					    "normalize.css": "7.0.0",
 | 
				
			||||||
    "nprogress": "0.2.0",
 | 
					    "nprogress": "0.2.0",
 | 
				
			||||||
    "screenfull": "4.0.0",
 | 
					    "path-to-regexp": "2.4.0",
 | 
				
			||||||
    "showdown": "1.8.6",
 | 
					    "screenfull": "4.2.0",
 | 
				
			||||||
    "sortablejs": "1.7.0",
 | 
					    "showdown": "1.9.0",
 | 
				
			||||||
    "tui-editor": "1.2.7",
 | 
					    "sortablejs": "1.8.4",
 | 
				
			||||||
    "vue": "2.5.17",
 | 
					    "tui-editor": "1.3.3",
 | 
				
			||||||
 | 
					    "vue": "2.6.10",
 | 
				
			||||||
    "vue-count-to": "1.0.13",
 | 
					    "vue-count-to": "1.0.13",
 | 
				
			||||||
    "vue-i18n": "7.3.2",
 | 
					    "vue-i18n": "7.3.2",
 | 
				
			||||||
    "vue-router": "3.0.2",
 | 
					    "vue-router": "3.0.2",
 | 
				
			||||||
    "vue-splitpane": "1.0.2",
 | 
					    "vue-splitpane": "1.0.4",
 | 
				
			||||||
    "vuedraggable": "^2.16.0",
 | 
					    "vuedraggable": "2.20.0",
 | 
				
			||||||
    "vuex": "3.0.1",
 | 
					    "vuex": "3.1.0",
 | 
				
			||||||
    "xlsx": "^0.11.16"
 | 
					    "xlsx": "0.14.1"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "autoprefixer": "8.5.0",
 | 
					    "@babel/core": "7.0.0",
 | 
				
			||||||
    "babel-core": "6.26.3",
 | 
					    "@babel/register": "7.0.0",
 | 
				
			||||||
    "babel-eslint": "8.2.6",
 | 
					    "@vue/cli-plugin-babel": "3.5.3",
 | 
				
			||||||
    "babel-helper-vue-jsx-merge-props": "2.0.3",
 | 
					    "@vue/cli-plugin-unit-jest": "3.5.3",
 | 
				
			||||||
    "babel-loader": "7.1.5",
 | 
					    "@vue/cli-service": "3.5.3",
 | 
				
			||||||
    "babel-plugin-dynamic-import-node": "2.0.0",
 | 
					    "@vue/test-utils": "1.0.0-beta.29",
 | 
				
			||||||
    "babel-plugin-syntax-jsx": "6.18.0",
 | 
					    "babel-core": "7.0.0-bridge.0",
 | 
				
			||||||
    "babel-plugin-transform-runtime": "6.23.0",
 | 
					    "babel-eslint": "10.0.1",
 | 
				
			||||||
    "babel-plugin-transform-vue-jsx": "3.7.0",
 | 
					    "babel-jest": "23.6.0",
 | 
				
			||||||
    "babel-preset-env": "1.7.0",
 | 
					    "chalk": "2.4.2",
 | 
				
			||||||
    "babel-preset-stage-2": "6.24.1",
 | 
					 | 
				
			||||||
    "chalk": "2.4.1",
 | 
					 | 
				
			||||||
    "compression-webpack-plugin": "2.0.0",
 | 
					 | 
				
			||||||
    "connect": "3.6.6",
 | 
					    "connect": "3.6.6",
 | 
				
			||||||
    "copy-webpack-plugin": "4.5.2",
 | 
					    "eslint": "5.15.3",
 | 
				
			||||||
    "cross-env": "5.2.0",
 | 
					    "eslint-plugin-vue": "5.2.2",
 | 
				
			||||||
    "css-loader": "1.0.0",
 | 
					    "html-webpack-plugin": "3.2.0",
 | 
				
			||||||
    "eslint": "4.19.1",
 | 
					    "husky": "1.3.1",
 | 
				
			||||||
    "eslint-friendly-formatter": "4.0.1",
 | 
					    "lint-staged": "8.1.5",
 | 
				
			||||||
    "eslint-loader": "2.0.0",
 | 
					    "mockjs": "1.0.1-beta3",
 | 
				
			||||||
    "eslint-plugin-vue": "4.7.1",
 | 
					    "node-sass": "^4.9.0",
 | 
				
			||||||
    "file-loader": "1.1.11",
 | 
					    "plop": "2.3.0",
 | 
				
			||||||
    "friendly-errors-webpack-plugin": "1.7.0",
 | 
					    "runjs": "^4.3.2",
 | 
				
			||||||
    "hash-sum": "1.0.2",
 | 
					    "sass-loader": "^7.1.0",
 | 
				
			||||||
    "html-webpack-plugin": "4.0.0-alpha",
 | 
					    "script-ext-html-webpack-plugin": "2.1.3",
 | 
				
			||||||
    "husky": "0.14.3",
 | 
					 | 
				
			||||||
    "lint-staged": "7.2.2",
 | 
					 | 
				
			||||||
    "mini-css-extract-plugin": "0.4.1",
 | 
					 | 
				
			||||||
    "node-notifier": "5.2.1",
 | 
					 | 
				
			||||||
    "node-sass": "^4.7.2",
 | 
					 | 
				
			||||||
    "optimize-css-assets-webpack-plugin": "5.0.0",
 | 
					 | 
				
			||||||
    "ora": "3.0.0",
 | 
					 | 
				
			||||||
    "path-to-regexp": "2.4.0",
 | 
					 | 
				
			||||||
    "portfinder": "1.0.13",
 | 
					 | 
				
			||||||
    "postcss-import": "11.1.0",
 | 
					 | 
				
			||||||
    "postcss-loader": "2.1.6",
 | 
					 | 
				
			||||||
    "postcss-url": "7.3.2",
 | 
					 | 
				
			||||||
    "rimraf": "2.6.2",
 | 
					 | 
				
			||||||
    "sass-loader": "7.0.3",
 | 
					 | 
				
			||||||
    "script-ext-html-webpack-plugin": "2.0.1",
 | 
					 | 
				
			||||||
    "script-loader": "0.7.2",
 | 
					    "script-loader": "0.7.2",
 | 
				
			||||||
    "semver": "5.5.0",
 | 
					    "serve-static": "^1.13.2",
 | 
				
			||||||
    "serve-static": "1.13.2",
 | 
					    "svg-sprite-loader": "4.1.3",
 | 
				
			||||||
    "shelljs": "0.8.2",
 | 
					    "svgo": "1.2.0",
 | 
				
			||||||
    "svg-sprite-loader": "3.8.0",
 | 
					    "vue-template-compiler": "2.6.10"
 | 
				
			||||||
    "svgo": "1.0.5",
 | 
					 | 
				
			||||||
    "uglifyjs-webpack-plugin": "1.2.7",
 | 
					 | 
				
			||||||
    "url-loader": "1.0.1",
 | 
					 | 
				
			||||||
    "vue-loader": "15.3.0",
 | 
					 | 
				
			||||||
    "vue-style-loader": "4.1.2",
 | 
					 | 
				
			||||||
    "vue-template-compiler": "2.5.17",
 | 
					 | 
				
			||||||
    "webpack": "4.16.5",
 | 
					 | 
				
			||||||
    "webpack-bundle-analyzer": "2.13.1",
 | 
					 | 
				
			||||||
    "webpack-cli": "3.1.0",
 | 
					 | 
				
			||||||
    "webpack-dev-server": "3.1.14",
 | 
					 | 
				
			||||||
    "webpack-merge": "4.1.4"
 | 
					 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "engines": {
 | 
					  "engines": {
 | 
				
			||||||
    "node": ">= 6.0.0",
 | 
					    "node": ">=8.9",
 | 
				
			||||||
    "npm": ">= 3.0.0"
 | 
					    "npm": ">= 3.0.0"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "browserslist": [
 | 
					  "browserslist": [
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										26
									
								
								plop-templates/component/index.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					{{#if template}}
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <div />
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					{{/if}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{#if script}}
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  name: '{{ properCase name }}',
 | 
				
			||||||
 | 
					  props: {},
 | 
				
			||||||
 | 
					  data() {
 | 
				
			||||||
 | 
					    return {}
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  created() {},
 | 
				
			||||||
 | 
					  mounted() {},
 | 
				
			||||||
 | 
					  methods: {}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					{{/if}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{#if style}}
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
 | 
					{{/if}}
 | 
				
			||||||
							
								
								
									
										55
									
								
								plop-templates/component/prompt.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					const { notEmpty } = require('../utils.js')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					  description: 'generate vue component',
 | 
				
			||||||
 | 
					  prompts: [{
 | 
				
			||||||
 | 
					    type: 'input',
 | 
				
			||||||
 | 
					    name: 'name',
 | 
				
			||||||
 | 
					    message: 'component name please',
 | 
				
			||||||
 | 
					    validate: notEmpty('name')
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    type: 'checkbox',
 | 
				
			||||||
 | 
					    name: 'blocks',
 | 
				
			||||||
 | 
					    message: 'Blocks:',
 | 
				
			||||||
 | 
					    choices: [{
 | 
				
			||||||
 | 
					      name: '<template>',
 | 
				
			||||||
 | 
					      value: 'template',
 | 
				
			||||||
 | 
					      checked: true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      name: '<script>',
 | 
				
			||||||
 | 
					      value: 'script',
 | 
				
			||||||
 | 
					      checked: true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      name: 'style',
 | 
				
			||||||
 | 
					      value: 'style',
 | 
				
			||||||
 | 
					      checked: true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    validate(value) {
 | 
				
			||||||
 | 
					      if (value.indexOf('script') === -1 && value.indexOf('template') === -1) {
 | 
				
			||||||
 | 
					        return 'Components require at least a <script> or <template> tag.'
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  actions: data => {
 | 
				
			||||||
 | 
					    const name = '{{properCase name}}'
 | 
				
			||||||
 | 
					    const actions = [{
 | 
				
			||||||
 | 
					      type: 'add',
 | 
				
			||||||
 | 
					      path: `src/components/${name}/index.vue`,
 | 
				
			||||||
 | 
					      templateFile: 'plop-templates/component/index.hbs',
 | 
				
			||||||
 | 
					      data: {
 | 
				
			||||||
 | 
					        name: name,
 | 
				
			||||||
 | 
					        template: data.blocks.includes('template'),
 | 
				
			||||||
 | 
					        script: data.blocks.includes('script'),
 | 
				
			||||||
 | 
					        style: data.blocks.includes('style')
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return actions
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										9
									
								
								plop-templates/utils.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					exports.notEmpty = name => {
 | 
				
			||||||
 | 
					  return v => {
 | 
				
			||||||
 | 
					    if (!v || v.trim === '') {
 | 
				
			||||||
 | 
					      return `${name} is required`
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      return true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								plop-templates/view/index.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					{{#if template}}
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <div />
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					{{/if}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{#if script}}
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  name: '{{ properCase name }}',
 | 
				
			||||||
 | 
					  props: {},
 | 
				
			||||||
 | 
					  data() {
 | 
				
			||||||
 | 
					    return {}
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  created() {},
 | 
				
			||||||
 | 
					  mounted() {},
 | 
				
			||||||
 | 
					  methods: {}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					{{/if}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{#if style}}
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
 | 
					{{/if}}
 | 
				
			||||||
							
								
								
									
										55
									
								
								plop-templates/view/prompt.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					const { notEmpty } = require('../utils.js')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					  description: 'generate a view',
 | 
				
			||||||
 | 
					  prompts: [{
 | 
				
			||||||
 | 
					    type: 'input',
 | 
				
			||||||
 | 
					    name: 'name',
 | 
				
			||||||
 | 
					    message: 'view name please',
 | 
				
			||||||
 | 
					    validate: notEmpty('name')
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    type: 'checkbox',
 | 
				
			||||||
 | 
					    name: 'blocks',
 | 
				
			||||||
 | 
					    message: 'Blocks:',
 | 
				
			||||||
 | 
					    choices: [{
 | 
				
			||||||
 | 
					      name: '<template>',
 | 
				
			||||||
 | 
					      value: 'template',
 | 
				
			||||||
 | 
					      checked: true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      name: '<script>',
 | 
				
			||||||
 | 
					      value: 'script',
 | 
				
			||||||
 | 
					      checked: true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      name: 'style',
 | 
				
			||||||
 | 
					      value: 'style',
 | 
				
			||||||
 | 
					      checked: true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    validate(value) {
 | 
				
			||||||
 | 
					      if (value.indexOf('script') === -1 && value.indexOf('template') === -1) {
 | 
				
			||||||
 | 
					        return 'View require at least a <script> or <template> tag.'
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  actions: data => {
 | 
				
			||||||
 | 
					    const name = '{{name}}'
 | 
				
			||||||
 | 
					    const actions = [{
 | 
				
			||||||
 | 
					      type: 'add',
 | 
				
			||||||
 | 
					      path: `src/views/${name}/index.vue`,
 | 
				
			||||||
 | 
					      templateFile: 'plop-templates/view/index.hbs',
 | 
				
			||||||
 | 
					      data: {
 | 
				
			||||||
 | 
					        name: name,
 | 
				
			||||||
 | 
					        template: data.blocks.includes('template'),
 | 
				
			||||||
 | 
					        script: data.blocks.includes('script'),
 | 
				
			||||||
 | 
					        style: data.blocks.includes('style')
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return actions
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										7
									
								
								plopfile.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					const viewGenerator = require('./plop-templates/view/prompt')
 | 
				
			||||||
 | 
					const componentGenerator = require('./plop-templates/component/prompt')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = function(plop) {
 | 
				
			||||||
 | 
					  plop.setGenerator('view', viewGenerator)
 | 
				
			||||||
 | 
					  plop.setGenerator('component', componentGenerator)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB  | 
@@ -5,10 +5,11 @@
 | 
				
			|||||||
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
 | 
					    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
 | 
				
			||||||
    <meta name="renderer" content="webkit">
 | 
					    <meta name="renderer" content="webkit">
 | 
				
			||||||
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
 | 
				
			||||||
    <title>vue-element-admin</title>
 | 
					    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
 | 
				
			||||||
 | 
					    <title><%= webpackConfig.name %></title>
 | 
				
			||||||
  </head>
 | 
					  </head>
 | 
				
			||||||
  <body>
 | 
					  <body>
 | 
				
			||||||
    <script src=<%= BASE_URL %>/tinymce4.7.5/tinymce.min.js></script>
 | 
					    <script src="<%= BASE_URL %>static/tinymce4.7.5/tinymce.min.js"></script>
 | 
				
			||||||
    <div id="app"></div>
 | 
					    <div id="app"></div>
 | 
				
			||||||
    <!-- built files will be auto injected -->
 | 
					    <!-- built files will be auto injected -->
 | 
				
			||||||
  </body>
 | 
					  </body>
 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 354 B After Width: | Height: | Size: 354 B  | 
| 
		 Before Width: | Height: | Size: 329 B After Width: | Height: | Size: 329 B  | 
| 
		 Before Width: | Height: | Size: 331 B After Width: | Height: | Size: 331 B  | 
| 
		 Before Width: | Height: | Size: 342 B After Width: | Height: | Size: 342 B  | 
| 
		 Before Width: | Height: | Size: 340 B After Width: | Height: | Size: 340 B  | 
| 
		 Before Width: | Height: | Size: 336 B After Width: | Height: | Size: 336 B  | 
| 
		 Before Width: | Height: | Size: 338 B After Width: | Height: | Size: 338 B  | 
| 
		 Before Width: | Height: | Size: 343 B After Width: | Height: | Size: 343 B  | 
| 
		 Before Width: | Height: | Size: 321 B After Width: | Height: | Size: 321 B  | 
| 
		 Before Width: | Height: | Size: 323 B After Width: | Height: | Size: 323 B  | 
| 
		 Before Width: | Height: | Size: 344 B After Width: | Height: | Size: 344 B  | 
| 
		 Before Width: | Height: | Size: 338 B After Width: | Height: | Size: 338 B  | 
| 
		 Before Width: | Height: | Size: 328 B After Width: | Height: | Size: 328 B  | 
| 
		 Before Width: | Height: | Size: 337 B After Width: | Height: | Size: 337 B  | 
| 
		 Before Width: | Height: | Size: 350 B After Width: | Height: | Size: 350 B  | 
| 
		 Before Width: | Height: | Size: 336 B After Width: | Height: | Size: 336 B  | 
| 
		 Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB  | 
| 
		 Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB  | 
| 
		 Before Width: | Height: | Size: 53 B After Width: | Height: | Size: 53 B  | 
| 
		 Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB  | 
| 
		 Before Width: | Height: | Size: 152 B After Width: | Height: | Size: 152 B  | 
| 
		 Before Width: | Height: | Size: 43 B After Width: | Height: | Size: 43 B  | 
@@ -1,11 +1,11 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div id="app">
 | 
					  <div id="app">
 | 
				
			||||||
    <router-view/>
 | 
					    <router-view />
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
export default{
 | 
					export default {
 | 
				
			||||||
  name: 'App'
 | 
					  name: 'App'
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,17 @@
 | 
				
			|||||||
import request from '@/utils/request'
 | 
					import request from '@/utils/request'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function userSearch(name) {
 | 
					export function searchUser(name) {
 | 
				
			||||||
  return request({
 | 
					  return request({
 | 
				
			||||||
    url: '/search/user',
 | 
					    url: '/search/user',
 | 
				
			||||||
    method: 'get',
 | 
					    method: 'get',
 | 
				
			||||||
    params: { name }
 | 
					    params: { name }
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function transactionList(query) {
 | 
				
			||||||
 | 
					  return request({
 | 
				
			||||||
 | 
					    url: '/transaction/list',
 | 
				
			||||||
 | 
					    method: 'get',
 | 
				
			||||||
 | 
					    params: query
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										38
									
								
								src/api/role.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					import request from '@/utils/request'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getRoutes() {
 | 
				
			||||||
 | 
					  return request({
 | 
				
			||||||
 | 
					    url: '/routes',
 | 
				
			||||||
 | 
					    method: 'get'
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getRoles() {
 | 
				
			||||||
 | 
					  return request({
 | 
				
			||||||
 | 
					    url: '/roles',
 | 
				
			||||||
 | 
					    method: 'get'
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function addRole(data) {
 | 
				
			||||||
 | 
					  return request({
 | 
				
			||||||
 | 
					    url: '/role',
 | 
				
			||||||
 | 
					    method: 'post',
 | 
				
			||||||
 | 
					    data
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function updateRole(id, data) {
 | 
				
			||||||
 | 
					  return request({
 | 
				
			||||||
 | 
					    url: `/role/${id}`,
 | 
				
			||||||
 | 
					    method: 'put',
 | 
				
			||||||
 | 
					    data
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function deleteRole(id) {
 | 
				
			||||||
 | 
					  return request({
 | 
				
			||||||
 | 
					    url: `/role/${id}`,
 | 
				
			||||||
 | 
					    method: 'delete'
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,9 +0,0 @@
 | 
				
			|||||||
import request from '@/utils/request'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function fetchList(query) {
 | 
					 | 
				
			||||||
  return request({
 | 
					 | 
				
			||||||
    url: '/transaction/list',
 | 
					 | 
				
			||||||
    method: 'get',
 | 
					 | 
				
			||||||
    params: query
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,25 +1,14 @@
 | 
				
			|||||||
import request from '@/utils/request'
 | 
					import request from '@/utils/request'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function loginByUsername(username, password) {
 | 
					export function login(data) {
 | 
				
			||||||
  const data = {
 | 
					 | 
				
			||||||
    username,
 | 
					 | 
				
			||||||
    password
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return request({
 | 
					  return request({
 | 
				
			||||||
    url: '/login/login',
 | 
					    url: '/user/login',
 | 
				
			||||||
    method: 'post',
 | 
					    method: 'post',
 | 
				
			||||||
    data
 | 
					    data
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function logout() {
 | 
					export function getInfo(token) {
 | 
				
			||||||
  return request({
 | 
					 | 
				
			||||||
    url: '/login/logout',
 | 
					 | 
				
			||||||
    method: 'post'
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function getUserInfo(token) {
 | 
					 | 
				
			||||||
  return request({
 | 
					  return request({
 | 
				
			||||||
    url: '/user/info',
 | 
					    url: '/user/info',
 | 
				
			||||||
    method: 'get',
 | 
					    method: 'get',
 | 
				
			||||||
@@ -27,3 +16,10 @@ export function getUserInfo(token) {
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function logout() {
 | 
				
			||||||
 | 
					  return request({
 | 
				
			||||||
 | 
					    url: '/user/logout',
 | 
				
			||||||
 | 
					    method: 'post'
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -4,7 +4,7 @@
 | 
				
			|||||||
      <svg width="16" height="16" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg" class="Icon Icon--backToTopArrow" aria-hidden="true" style="height: 16px; width: 16px;">
 | 
					      <svg width="16" height="16" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg" class="Icon Icon--backToTopArrow" aria-hidden="true" style="height: 16px; width: 16px;">
 | 
				
			||||||
        <title>回到顶部</title>
 | 
					        <title>回到顶部</title>
 | 
				
			||||||
        <g>
 | 
					        <g>
 | 
				
			||||||
          <path d="M12.036 15.59c0 .55-.453.995-.997.995H5.032c-.55 0-.997-.445-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29c.39-.39 1.026-.385 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" fill-rule="evenodd"/>
 | 
					          <path d="M12.036 15.59c0 .55-.453.995-.997.995H5.032c-.55 0-.997-.445-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29c.39-.39 1.026-.385 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" fill-rule="evenodd" />
 | 
				
			||||||
        </g>
 | 
					        </g>
 | 
				
			||||||
      </svg>
 | 
					      </svg>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
@@ -88,29 +88,29 @@ export default {
 | 
				
			|||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style scoped>
 | 
					<style scoped>
 | 
				
			||||||
  .back-to-ceiling {
 | 
					.back-to-ceiling {
 | 
				
			||||||
    position: fixed;
 | 
					  position: fixed;
 | 
				
			||||||
    display: inline-block;
 | 
					  display: inline-block;
 | 
				
			||||||
    text-align: center;
 | 
					  text-align: center;
 | 
				
			||||||
    cursor: pointer;
 | 
					  cursor: pointer;
 | 
				
			||||||
  }
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .back-to-ceiling:hover {
 | 
					.back-to-ceiling:hover {
 | 
				
			||||||
    background: #d5dbe7;
 | 
					  background: #d5dbe7;
 | 
				
			||||||
  }
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .fade-enter-active,
 | 
					.fade-enter-active,
 | 
				
			||||||
  .fade-leave-active {
 | 
					.fade-leave-active {
 | 
				
			||||||
    transition: opacity .5s;
 | 
					  transition: opacity .5s;
 | 
				
			||||||
  }
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .fade-enter,
 | 
					.fade-enter,
 | 
				
			||||||
  .fade-leave-to {
 | 
					.fade-leave-to {
 | 
				
			||||||
    opacity: 0
 | 
					  opacity: 0
 | 
				
			||||||
  }
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .back-to-ceiling .Icon {
 | 
					.back-to-ceiling .Icon {
 | 
				
			||||||
    fill: #9aaabf;
 | 
					  fill: #9aaabf;
 | 
				
			||||||
    background: none;
 | 
					  background: none;
 | 
				
			||||||
  }
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@
 | 
				
			|||||||
    <transition-group name="breadcrumb">
 | 
					    <transition-group name="breadcrumb">
 | 
				
			||||||
      <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
 | 
					      <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
 | 
				
			||||||
        <span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{
 | 
					        <span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{
 | 
				
			||||||
        generateTitle(item.meta.title) }}</span>
 | 
					          generateTitle(item.meta.title) }}</span>
 | 
				
			||||||
        <a v-else @click.prevent="handleLink(item)">{{ generateTitle(item.meta.title) }}</a>
 | 
					        <a v-else @click.prevent="handleLink(item)">{{ generateTitle(item.meta.title) }}</a>
 | 
				
			||||||
      </el-breadcrumb-item>
 | 
					      </el-breadcrumb-item>
 | 
				
			||||||
    </transition-group>
 | 
					    </transition-group>
 | 
				
			||||||
@@ -58,15 +58,16 @@ export default {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style rel="stylesheet/scss" lang="scss" scoped>
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
  .app-breadcrumb.el-breadcrumb {
 | 
					.app-breadcrumb.el-breadcrumb {
 | 
				
			||||||
    display: inline-block;
 | 
					  display: inline-block;
 | 
				
			||||||
    font-size: 14px;
 | 
					  font-size: 14px;
 | 
				
			||||||
    line-height: 50px;
 | 
					  line-height: 50px;
 | 
				
			||||||
    margin-left: 8px;
 | 
					  margin-left: 8px;
 | 
				
			||||||
    .no-redirect {
 | 
					
 | 
				
			||||||
      color: #97a8be;
 | 
					  .no-redirect {
 | 
				
			||||||
      cursor: text;
 | 
					    color: #97a8be;
 | 
				
			||||||
    }
 | 
					    cursor: text;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div :class="className" :id="id" :style="{height:height,width:width}"/>
 | 
					  <div :id="id" :class="className" :style="{height:height,width:width}" />
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div :class="className" :id="id" :style="{height:height,width:width}"/>
 | 
					  <div :id="id" :class="className" :style="{height:height,width:width}" />
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div :class="className" :id="id" :style="{height:height,width:width}"/>
 | 
					  <div :id="id" :class="className" :style="{height:height,width:width}" />
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,12 +2,14 @@
 | 
				
			|||||||
  <div class="dndList">
 | 
					  <div class="dndList">
 | 
				
			||||||
    <div :style="{width:width1}" class="dndList-list">
 | 
					    <div :style="{width:width1}" class="dndList-list">
 | 
				
			||||||
      <h3>{{ list1Title }}</h3>
 | 
					      <h3>{{ list1Title }}</h3>
 | 
				
			||||||
      <draggable :list="list1" :options="{group:'article'}" class="dragArea">
 | 
					      <draggable :list="list1" group="article" class="dragArea">
 | 
				
			||||||
        <div v-for="element in list1" :key="element.id" class="list-complete-item">
 | 
					        <div v-for="element in list1" :key="element.id" class="list-complete-item">
 | 
				
			||||||
          <div class="list-complete-item-handle">{{ element.id }}[{{ element.author }}] {{ element.title }}</div>
 | 
					          <div class="list-complete-item-handle">
 | 
				
			||||||
 | 
					            {{ element.id }}[{{ element.author }}] {{ element.title }}
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
          <div style="position:absolute;right:0px;">
 | 
					          <div style="position:absolute;right:0px;">
 | 
				
			||||||
            <span style="float: right ;margin-top: -20px;margin-right:5px;" @click="deleteEle(element)">
 | 
					            <span style="float: right ;margin-top: -20px;margin-right:5px;" @click="deleteEle(element)">
 | 
				
			||||||
              <i style="color:#ff4949" class="el-icon-delete"/>
 | 
					              <i style="color:#ff4949" class="el-icon-delete" />
 | 
				
			||||||
            </span>
 | 
					            </span>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
@@ -15,9 +17,11 @@
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div :style="{width:width2}" class="dndList-list">
 | 
					    <div :style="{width:width2}" class="dndList-list">
 | 
				
			||||||
      <h3>{{ list2Title }}</h3>
 | 
					      <h3>{{ list2Title }}</h3>
 | 
				
			||||||
      <draggable :list="list2" :options="{group:'article'}" class="dragArea">
 | 
					      <draggable :list="list2" group="article" class="dragArea">
 | 
				
			||||||
        <div v-for="element in list2" :key="element.id" class="list-complete-item">
 | 
					        <div v-for="element in list2" :key="element.id" class="list-complete-item">
 | 
				
			||||||
          <div class="list-complete-item-handle2" @click="pushEle(element)">{{ element.id }} [{{ element.author }}] {{ element.title }}</div>
 | 
					          <div class="list-complete-item-handle2" @click="pushEle(element)">
 | 
				
			||||||
 | 
					            {{ element.id }} [{{ element.author }}] {{ element.title }}
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </draggable>
 | 
					      </draggable>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
@@ -95,7 +99,7 @@ export default {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style rel="stylesheet/scss" lang="scss" scoped>
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
.dndList {
 | 
					.dndList {
 | 
				
			||||||
  background: #fff;
 | 
					  background: #fff;
 | 
				
			||||||
  padding-bottom: 40px;
 | 
					  padding-bottom: 40px;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <el-select ref="dragSelect" v-model="selectVal" v-bind="$attrs" class="drag-select" multiple v-on="$listeners">
 | 
					  <el-select ref="dragSelect" v-model="selectVal" v-bind="$attrs" class="drag-select" multiple v-on="$listeners">
 | 
				
			||||||
    <slot/>
 | 
					    <slot />
 | 
				
			||||||
  </el-select>
 | 
					  </el-select>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div :ref="id" :action="url" :id="id" class="dropzone">
 | 
					  <div :id="id" :ref="id" :action="url" class="dropzone">
 | 
				
			||||||
    <input type="file" name="file">
 | 
					    <input type="file" name="file">
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
@@ -237,7 +237,7 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    .dropzone .dz-preview:hover .dz-image img {
 | 
					    .dropzone .dz-preview:hover .dz-image img {
 | 
				
			||||||
        transform: none;
 | 
					        transform: none;
 | 
				
			||||||
        -webkit-filter: none;
 | 
					        filter: none;
 | 
				
			||||||
        width: 100%;
 | 
					        width: 100%;
 | 
				
			||||||
        height: 100%;
 | 
					        height: 100%;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,20 +9,26 @@
 | 
				
			|||||||
    <el-dialog :visible.sync="dialogTableVisible" title="Error Log" width="80%">
 | 
					    <el-dialog :visible.sync="dialogTableVisible" title="Error Log" width="80%">
 | 
				
			||||||
      <el-table :data="errorLogs" border>
 | 
					      <el-table :data="errorLogs" border>
 | 
				
			||||||
        <el-table-column label="Message">
 | 
					        <el-table-column label="Message">
 | 
				
			||||||
          <template slot-scope="scope">
 | 
					          <template slot-scope="{row}">
 | 
				
			||||||
            <div>
 | 
					            <div>
 | 
				
			||||||
              <span class="message-title">Msg:</span>
 | 
					              <span class="message-title">Msg:</span>
 | 
				
			||||||
              <el-tag type="danger">{{ scope.row.err.message }}</el-tag>
 | 
					              <el-tag type="danger">
 | 
				
			||||||
 | 
					                {{ row.err.message }}
 | 
				
			||||||
 | 
					              </el-tag>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <br>
 | 
					            <br>
 | 
				
			||||||
            <div>
 | 
					            <div>
 | 
				
			||||||
              <span class="message-title" style="padding-right: 10px;">Info: </span>
 | 
					              <span class="message-title" style="padding-right: 10px;">Info: </span>
 | 
				
			||||||
              <el-tag type="warning">{{ scope.row.vm.$vnode.tag }} error in {{ scope.row.info }}</el-tag>
 | 
					              <el-tag type="warning">
 | 
				
			||||||
 | 
					                {{ row.vm.$vnode.tag }} error in {{ row.info }}
 | 
				
			||||||
 | 
					              </el-tag>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <br>
 | 
					            <br>
 | 
				
			||||||
            <div>
 | 
					            <div>
 | 
				
			||||||
              <span class="message-title" style="padding-right: 16px;">Url: </span>
 | 
					              <span class="message-title" style="padding-right: 16px;">Url: </span>
 | 
				
			||||||
              <el-tag type="success">{{ scope.row.url }}</el-tag>
 | 
					              <el-tag type="success">
 | 
				
			||||||
 | 
					                {{ row.url }}
 | 
				
			||||||
 | 
					              </el-tag>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </template>
 | 
					          </template>
 | 
				
			||||||
        </el-table-column>
 | 
					        </el-table-column>
 | 
				
			||||||
@@ -33,7 +39,6 @@
 | 
				
			|||||||
        </el-table-column>
 | 
					        </el-table-column>
 | 
				
			||||||
      </el-table>
 | 
					      </el-table>
 | 
				
			||||||
    </el-dialog>
 | 
					    </el-dialog>
 | 
				
			||||||
 | 
					 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,17 +5,20 @@
 | 
				
			|||||||
      height="80"
 | 
					      height="80"
 | 
				
			||||||
      viewBox="0 0 250 250"
 | 
					      viewBox="0 0 250 250"
 | 
				
			||||||
      style="fill:#40c9c6; color:#fff;"
 | 
					      style="fill:#40c9c6; color:#fff;"
 | 
				
			||||||
      aria-hidden="true">
 | 
					      aria-hidden="true"
 | 
				
			||||||
      <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"/>
 | 
					    >
 | 
				
			||||||
 | 
					      <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" />
 | 
				
			||||||
      <path
 | 
					      <path
 | 
				
			||||||
        d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
 | 
					        d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
 | 
				
			||||||
        fill="currentColor"
 | 
					        fill="currentColor"
 | 
				
			||||||
        style="transform-origin: 130px 106px;"
 | 
					        style="transform-origin: 130px 106px;"
 | 
				
			||||||
        class="octo-arm"/>
 | 
					        class="octo-arm"
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
      <path
 | 
					      <path
 | 
				
			||||||
        d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
 | 
					        d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
 | 
				
			||||||
        fill="currentColor"
 | 
					        fill="currentColor"
 | 
				
			||||||
        class="octo-body"/>
 | 
					        class="octo-body"
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
    </svg>
 | 
					    </svg>
 | 
				
			||||||
  </a>
 | 
					  </a>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,10 +20,11 @@ export default {
 | 
				
			|||||||
    isActive: {
 | 
					    isActive: {
 | 
				
			||||||
      type: Boolean,
 | 
					      type: Boolean,
 | 
				
			||||||
      default: false
 | 
					      default: false
 | 
				
			||||||
    },
 | 
					    }
 | 
				
			||||||
    toggleClick: {
 | 
					  },
 | 
				
			||||||
      type: Function,
 | 
					  methods: {
 | 
				
			||||||
      default: null
 | 
					    toggleClick() {
 | 
				
			||||||
 | 
					      this.$emit('toggleClick')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div :class="{'show':show}" class="header-search">
 | 
					  <div :class="{'show':show}" class="header-search">
 | 
				
			||||||
    <svg-icon class-name="search-icon" icon-class="search" @click="click" />
 | 
					    <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
 | 
				
			||||||
    <el-select
 | 
					    <el-select
 | 
				
			||||||
      ref="headerSearchSelect"
 | 
					      ref="headerSearchSelect"
 | 
				
			||||||
      v-model="search"
 | 
					      v-model="search"
 | 
				
			||||||
@@ -10,13 +10,16 @@
 | 
				
			|||||||
      remote
 | 
					      remote
 | 
				
			||||||
      placeholder="Search"
 | 
					      placeholder="Search"
 | 
				
			||||||
      class="header-search-select"
 | 
					      class="header-search-select"
 | 
				
			||||||
      @change="change">
 | 
					      @change="change"
 | 
				
			||||||
      <el-option v-for="item in options" :key="item.path" :value="item" :label="item.title.join(' > ')"/>
 | 
					    >
 | 
				
			||||||
 | 
					      <el-option v-for="item in options" :key="item.path" :value="item" :label="item.title.join(' > ')" />
 | 
				
			||||||
    </el-select>
 | 
					    </el-select>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
 | 
					// fuse is a lightweight fuzzy-search module
 | 
				
			||||||
 | 
					// make search results more in line with expectations
 | 
				
			||||||
import Fuse from 'fuse.js'
 | 
					import Fuse from 'fuse.js'
 | 
				
			||||||
import path from 'path'
 | 
					import path from 'path'
 | 
				
			||||||
import i18n from '@/lang'
 | 
					import i18n from '@/lang'
 | 
				
			||||||
@@ -33,8 +36,8 @@ export default {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
    routers() {
 | 
					    routes() {
 | 
				
			||||||
      return this.$store.getters.permission_routers
 | 
					      return this.$store.getters.permission_routes
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    lang() {
 | 
					    lang() {
 | 
				
			||||||
      return this.$store.getters.language
 | 
					      return this.$store.getters.language
 | 
				
			||||||
@@ -42,10 +45,10 @@ export default {
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  watch: {
 | 
					  watch: {
 | 
				
			||||||
    lang() {
 | 
					    lang() {
 | 
				
			||||||
      this.searchPool = this.generateRouters(this.routers)
 | 
					      this.searchPool = this.generateRoutes(this.routes)
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    routers() {
 | 
					    routes() {
 | 
				
			||||||
      this.searchPool = this.generateRouters(this.routers)
 | 
					      this.searchPool = this.generateRoutes(this.routes)
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    searchPool(list) {
 | 
					    searchPool(list) {
 | 
				
			||||||
      this.initFuse(list)
 | 
					      this.initFuse(list)
 | 
				
			||||||
@@ -59,7 +62,7 @@ export default {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  mounted() {
 | 
					  mounted() {
 | 
				
			||||||
    this.searchPool = this.generateRouters(this.routers)
 | 
					    this.searchPool = this.generateRoutes(this.routes)
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
    click() {
 | 
					    click() {
 | 
				
			||||||
@@ -100,10 +103,10 @@ export default {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    // Filter out the routes that can be displayed in the sidebar
 | 
					    // Filter out the routes that can be displayed in the sidebar
 | 
				
			||||||
    // And generate the internationalized title
 | 
					    // And generate the internationalized title
 | 
				
			||||||
    generateRouters(routers, basePath = '/', prefixTitle = []) {
 | 
					    generateRoutes(routes, basePath = '/', prefixTitle = []) {
 | 
				
			||||||
      let res = []
 | 
					      let res = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      for (const router of routers) {
 | 
					      for (const router of routes) {
 | 
				
			||||||
        // skip hidden router
 | 
					        // skip hidden router
 | 
				
			||||||
        if (router.hidden) { continue }
 | 
					        if (router.hidden) { continue }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -125,11 +128,11 @@ export default {
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // recursive child routers
 | 
					        // recursive child routes
 | 
				
			||||||
        if (router.children) {
 | 
					        if (router.children) {
 | 
				
			||||||
          const tempRouters = this.generateRouters(router.children, data.path, data.title)
 | 
					          const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
 | 
				
			||||||
          if (tempRouters.length >= 1) {
 | 
					          if (tempRoutes.length >= 1) {
 | 
				
			||||||
            res = [...res, ...tempRouters]
 | 
					            res = [...res, ...tempRoutes]
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,22 +2,22 @@
 | 
				
			|||||||
  <div v-show="value" class="vue-image-crop-upload">
 | 
					  <div v-show="value" class="vue-image-crop-upload">
 | 
				
			||||||
    <div class="vicp-wrap">
 | 
					    <div class="vicp-wrap">
 | 
				
			||||||
      <div class="vicp-close" @click="off">
 | 
					      <div class="vicp-close" @click="off">
 | 
				
			||||||
        <i class="vicp-icon4"/>
 | 
					        <i class="vicp-icon4" />
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div v-show="step == 1" class="vicp-step1">
 | 
					      <div v-show="step == 1" class="vicp-step1">
 | 
				
			||||||
        <div class="vicp-drop-area" @dragleave="preventDefault" @dragover="preventDefault" @dragenter="preventDefault" @click="handleClick" @drop="handleChange">
 | 
					        <div class="vicp-drop-area" @dragleave="preventDefault" @dragover="preventDefault" @dragenter="preventDefault" @click="handleClick" @drop="handleChange">
 | 
				
			||||||
          <i v-show="loading != 1" class="vicp-icon1">
 | 
					          <i v-show="loading != 1" class="vicp-icon1">
 | 
				
			||||||
            <i class="vicp-icon1-arrow"/>
 | 
					            <i class="vicp-icon1-arrow" />
 | 
				
			||||||
            <i class="vicp-icon1-body"/>
 | 
					            <i class="vicp-icon1-body" />
 | 
				
			||||||
            <i class="vicp-icon1-bottom"/>
 | 
					            <i class="vicp-icon1-bottom" />
 | 
				
			||||||
          </i>
 | 
					          </i>
 | 
				
			||||||
          <span v-show="loading !== 1" class="vicp-hint">{{ lang.hint }}</span>
 | 
					          <span v-show="loading !== 1" class="vicp-hint">{{ lang.hint }}</span>
 | 
				
			||||||
          <span v-show="!isSupported" class="vicp-no-supported-hint">{{ lang.noSupported }}</span>
 | 
					          <span v-show="!isSupported" class="vicp-no-supported-hint">{{ lang.noSupported }}</span>
 | 
				
			||||||
          <input v-show="false" v-if="step == 1" ref="fileinput" type="file" @change="handleChange">
 | 
					          <input v-show="false" v-if="step == 1" ref="fileinput" type="file" @change="handleChange">
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div v-show="hasError" class="vicp-error">
 | 
					        <div v-show="hasError" class="vicp-error">
 | 
				
			||||||
          <i class="vicp-icon2"/> {{ errorMsg }}
 | 
					          <i class="vicp-icon2" /> {{ errorMsg }}
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="vicp-operate">
 | 
					        <div class="vicp-operate">
 | 
				
			||||||
          <a @click="off" @mousedown="ripple">{{ lang.btn.off }}</a>
 | 
					          <a @click="off" @mousedown="ripple">{{ lang.btn.off }}</a>
 | 
				
			||||||
@@ -48,15 +48,16 @@
 | 
				
			|||||||
                @mousedown="imgStartMove"
 | 
					                @mousedown="imgStartMove"
 | 
				
			||||||
                @mousemove="imgMove"
 | 
					                @mousemove="imgMove"
 | 
				
			||||||
                @mouseup="createImg"
 | 
					                @mouseup="createImg"
 | 
				
			||||||
                @mouseout="createImg">
 | 
					                @mouseout="createImg"
 | 
				
			||||||
              <div :style="sourceImgShadeStyle" class="vicp-img-shade vicp-img-shade-1"/>
 | 
					              >
 | 
				
			||||||
              <div :style="sourceImgShadeStyle" class="vicp-img-shade vicp-img-shade-2"/>
 | 
					              <div :style="sourceImgShadeStyle" class="vicp-img-shade vicp-img-shade-1" />
 | 
				
			||||||
 | 
					              <div :style="sourceImgShadeStyle" class="vicp-img-shade vicp-img-shade-2" />
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <div class="vicp-range">
 | 
					            <div class="vicp-range">
 | 
				
			||||||
              <input :value="scale.range" type="range" step="1" min="0" max="100" @input="zoomChange">
 | 
					              <input :value="scale.range" type="range" step="1" min="0" max="100" @input="zoomChange">
 | 
				
			||||||
              <i class="vicp-icon5" @mousedown="startZoomSub" @mouseout="endZoomSub" @mouseup="endZoomSub"/>
 | 
					              <i class="vicp-icon5" @mousedown="startZoomSub" @mouseout="endZoomSub" @mouseup="endZoomSub" />
 | 
				
			||||||
              <i class="vicp-icon6" @mousedown="startZoomAdd" @mouseout="endZoomAdd" @mouseup="endZoomAdd"/>
 | 
					              <i class="vicp-icon6" @mousedown="startZoomAdd" @mouseout="endZoomAdd" @mouseup="endZoomAdd" />
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <div v-if="!noRotate" class="vicp-rotate">
 | 
					            <div v-if="!noRotate" class="vicp-rotate">
 | 
				
			||||||
@@ -87,13 +88,13 @@
 | 
				
			|||||||
        <div class="vicp-upload">
 | 
					        <div class="vicp-upload">
 | 
				
			||||||
          <span v-show="loading === 1" class="vicp-loading">{{ lang.loading }}</span>
 | 
					          <span v-show="loading === 1" class="vicp-loading">{{ lang.loading }}</span>
 | 
				
			||||||
          <div class="vicp-progress-wrap">
 | 
					          <div class="vicp-progress-wrap">
 | 
				
			||||||
            <span v-show="loading === 1" :style="progressStyle" class="vicp-progress"/>
 | 
					            <span v-show="loading === 1" :style="progressStyle" class="vicp-progress" />
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
          <div v-show="hasError" class="vicp-error">
 | 
					          <div v-show="hasError" class="vicp-error">
 | 
				
			||||||
            <i class="vicp-icon2"/> {{ errorMsg }}
 | 
					            <i class="vicp-icon2" /> {{ errorMsg }}
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
          <div v-show="loading === 2" class="vicp-success">
 | 
					          <div v-show="loading === 2" class="vicp-success">
 | 
				
			||||||
            <i class="vicp-icon3"/> {{ lang.success }}
 | 
					            <i class="vicp-icon3" /> {{ lang.success }}
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="vicp-operate">
 | 
					        <div class="vicp-operate">
 | 
				
			||||||
@@ -101,7 +102,7 @@
 | 
				
			|||||||
          <a @click="off" @mousedown="ripple">{{ lang.btn.close }}</a>
 | 
					          <a @click="off" @mousedown="ripple">{{ lang.btn.close }}</a>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <canvas v-show="false" ref="canvas" :width="width" :height="height"/>
 | 
					      <canvas v-show="false" ref="canvas" :width="width" :height="height" />
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div class="json-editor">
 | 
					  <div class="json-editor">
 | 
				
			||||||
    <textarea ref="textarea"/>
 | 
					    <textarea ref="textarea" />
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,8 +5,9 @@
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <draggable
 | 
					    <draggable
 | 
				
			||||||
      :list="list"
 | 
					      :list="list"
 | 
				
			||||||
      :options="options"
 | 
					      v-bind="$attrs"
 | 
				
			||||||
      class="board-column-content">
 | 
					      class="board-column-content"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
      <div v-for="element in list" :key="element.id" class="board-item">
 | 
					      <div v-for="element in list" :key="element.id" class="board-item">
 | 
				
			||||||
        {{ element.name }} {{ element.id }}
 | 
					        {{ element.name }} {{ element.id }}
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,9 +4,15 @@
 | 
				
			|||||||
      <svg-icon class-name="international-icon" icon-class="language" />
 | 
					      <svg-icon class-name="international-icon" icon-class="language" />
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <el-dropdown-menu slot="dropdown">
 | 
					    <el-dropdown-menu slot="dropdown">
 | 
				
			||||||
      <el-dropdown-item :disabled="language==='zh'" command="zh">中文</el-dropdown-item>
 | 
					      <el-dropdown-item :disabled="language==='zh'" command="zh">
 | 
				
			||||||
      <el-dropdown-item :disabled="language==='en'" command="en">English</el-dropdown-item>
 | 
					        中文
 | 
				
			||||||
      <el-dropdown-item :disabled="language==='es'" command="es">Español</el-dropdown-item>
 | 
					      </el-dropdown-item>
 | 
				
			||||||
 | 
					      <el-dropdown-item :disabled="language==='en'" command="en">
 | 
				
			||||||
 | 
					        English
 | 
				
			||||||
 | 
					      </el-dropdown-item>
 | 
				
			||||||
 | 
					      <el-dropdown-item :disabled="language==='es'" command="es">
 | 
				
			||||||
 | 
					        Español
 | 
				
			||||||
 | 
					      </el-dropdown-item>
 | 
				
			||||||
    </el-dropdown-menu>
 | 
					    </el-dropdown-menu>
 | 
				
			||||||
  </el-dropdown>
 | 
					  </el-dropdown>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
@@ -21,7 +27,7 @@ export default {
 | 
				
			|||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
    handleSetLanguage(lang) {
 | 
					    handleSetLanguage(lang) {
 | 
				
			||||||
      this.$i18n.locale = lang
 | 
					      this.$i18n.locale = lang
 | 
				
			||||||
      this.$store.dispatch('setLanguage', lang)
 | 
					      this.$store.dispatch('app/setLanguage', lang)
 | 
				
			||||||
      this.$message({
 | 
					      this.$message({
 | 
				
			||||||
        message: 'Switch Language Success',
 | 
					        message: 'Switch Language Success',
 | 
				
			||||||
        type: 'success'
 | 
					        type: 'success'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,12 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div :class="computedClasses" class="material-input__component">
 | 
					  <div :class="computedClasses" class="material-input__component">
 | 
				
			||||||
    <div :class="{iconClass:icon}">
 | 
					    <div :class="{iconClass:icon}">
 | 
				
			||||||
      <i v-if="icon" :class="['el-icon-' + icon]" class="el-input__icon material-input__icon"/>
 | 
					      <i v-if="icon" :class="['el-icon-' + icon]" class="el-input__icon material-input__icon" />
 | 
				
			||||||
      <input
 | 
					      <input
 | 
				
			||||||
        v-if="type === 'email'"
 | 
					        v-if="type === 'email'"
 | 
				
			||||||
 | 
					        v-model="currentValue"
 | 
				
			||||||
        :name="name"
 | 
					        :name="name"
 | 
				
			||||||
        :placeholder="fillPlaceHolder"
 | 
					        :placeholder="fillPlaceHolder"
 | 
				
			||||||
        v-model="currentValue"
 | 
					 | 
				
			||||||
        :readonly="readonly"
 | 
					        :readonly="readonly"
 | 
				
			||||||
        :disabled="disabled"
 | 
					        :disabled="disabled"
 | 
				
			||||||
        :autoComplete="autoComplete"
 | 
					        :autoComplete="autoComplete"
 | 
				
			||||||
@@ -15,12 +15,13 @@
 | 
				
			|||||||
        class="material-input"
 | 
					        class="material-input"
 | 
				
			||||||
        @focus="handleMdFocus"
 | 
					        @focus="handleMdFocus"
 | 
				
			||||||
        @blur="handleMdBlur"
 | 
					        @blur="handleMdBlur"
 | 
				
			||||||
        @input="handleModelInput">
 | 
					        @input="handleModelInput"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
      <input
 | 
					      <input
 | 
				
			||||||
        v-if="type === 'url'"
 | 
					        v-if="type === 'url'"
 | 
				
			||||||
 | 
					        v-model="currentValue"
 | 
				
			||||||
        :name="name"
 | 
					        :name="name"
 | 
				
			||||||
        :placeholder="fillPlaceHolder"
 | 
					        :placeholder="fillPlaceHolder"
 | 
				
			||||||
        v-model="currentValue"
 | 
					 | 
				
			||||||
        :readonly="readonly"
 | 
					        :readonly="readonly"
 | 
				
			||||||
        :disabled="disabled"
 | 
					        :disabled="disabled"
 | 
				
			||||||
        :autoComplete="autoComplete"
 | 
					        :autoComplete="autoComplete"
 | 
				
			||||||
@@ -29,12 +30,13 @@
 | 
				
			|||||||
        class="material-input"
 | 
					        class="material-input"
 | 
				
			||||||
        @focus="handleMdFocus"
 | 
					        @focus="handleMdFocus"
 | 
				
			||||||
        @blur="handleMdBlur"
 | 
					        @blur="handleMdBlur"
 | 
				
			||||||
        @input="handleModelInput">
 | 
					        @input="handleModelInput"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
      <input
 | 
					      <input
 | 
				
			||||||
        v-if="type === 'number'"
 | 
					        v-if="type === 'number'"
 | 
				
			||||||
 | 
					        v-model="currentValue"
 | 
				
			||||||
        :name="name"
 | 
					        :name="name"
 | 
				
			||||||
        :placeholder="fillPlaceHolder"
 | 
					        :placeholder="fillPlaceHolder"
 | 
				
			||||||
        v-model="currentValue"
 | 
					 | 
				
			||||||
        :step="step"
 | 
					        :step="step"
 | 
				
			||||||
        :readonly="readonly"
 | 
					        :readonly="readonly"
 | 
				
			||||||
        :disabled="disabled"
 | 
					        :disabled="disabled"
 | 
				
			||||||
@@ -48,12 +50,13 @@
 | 
				
			|||||||
        class="material-input"
 | 
					        class="material-input"
 | 
				
			||||||
        @focus="handleMdFocus"
 | 
					        @focus="handleMdFocus"
 | 
				
			||||||
        @blur="handleMdBlur"
 | 
					        @blur="handleMdBlur"
 | 
				
			||||||
        @input="handleModelInput">
 | 
					        @input="handleModelInput"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
      <input
 | 
					      <input
 | 
				
			||||||
        v-if="type === 'password'"
 | 
					        v-if="type === 'password'"
 | 
				
			||||||
 | 
					        v-model="currentValue"
 | 
				
			||||||
        :name="name"
 | 
					        :name="name"
 | 
				
			||||||
        :placeholder="fillPlaceHolder"
 | 
					        :placeholder="fillPlaceHolder"
 | 
				
			||||||
        v-model="currentValue"
 | 
					 | 
				
			||||||
        :readonly="readonly"
 | 
					        :readonly="readonly"
 | 
				
			||||||
        :disabled="disabled"
 | 
					        :disabled="disabled"
 | 
				
			||||||
        :autoComplete="autoComplete"
 | 
					        :autoComplete="autoComplete"
 | 
				
			||||||
@@ -64,12 +67,13 @@
 | 
				
			|||||||
        class="material-input"
 | 
					        class="material-input"
 | 
				
			||||||
        @focus="handleMdFocus"
 | 
					        @focus="handleMdFocus"
 | 
				
			||||||
        @blur="handleMdBlur"
 | 
					        @blur="handleMdBlur"
 | 
				
			||||||
        @input="handleModelInput">
 | 
					        @input="handleModelInput"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
      <input
 | 
					      <input
 | 
				
			||||||
        v-if="type === 'tel'"
 | 
					        v-if="type === 'tel'"
 | 
				
			||||||
 | 
					        v-model="currentValue"
 | 
				
			||||||
        :name="name"
 | 
					        :name="name"
 | 
				
			||||||
        :placeholder="fillPlaceHolder"
 | 
					        :placeholder="fillPlaceHolder"
 | 
				
			||||||
        v-model="currentValue"
 | 
					 | 
				
			||||||
        :readonly="readonly"
 | 
					        :readonly="readonly"
 | 
				
			||||||
        :disabled="disabled"
 | 
					        :disabled="disabled"
 | 
				
			||||||
        :autoComplete="autoComplete"
 | 
					        :autoComplete="autoComplete"
 | 
				
			||||||
@@ -78,12 +82,13 @@
 | 
				
			|||||||
        class="material-input"
 | 
					        class="material-input"
 | 
				
			||||||
        @focus="handleMdFocus"
 | 
					        @focus="handleMdFocus"
 | 
				
			||||||
        @blur="handleMdBlur"
 | 
					        @blur="handleMdBlur"
 | 
				
			||||||
        @input="handleModelInput">
 | 
					        @input="handleModelInput"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
      <input
 | 
					      <input
 | 
				
			||||||
        v-if="type === 'text'"
 | 
					        v-if="type === 'text'"
 | 
				
			||||||
 | 
					        v-model="currentValue"
 | 
				
			||||||
        :name="name"
 | 
					        :name="name"
 | 
				
			||||||
        :placeholder="fillPlaceHolder"
 | 
					        :placeholder="fillPlaceHolder"
 | 
				
			||||||
        v-model="currentValue"
 | 
					 | 
				
			||||||
        :readonly="readonly"
 | 
					        :readonly="readonly"
 | 
				
			||||||
        :disabled="disabled"
 | 
					        :disabled="disabled"
 | 
				
			||||||
        :autoComplete="autoComplete"
 | 
					        :autoComplete="autoComplete"
 | 
				
			||||||
@@ -94,10 +99,11 @@
 | 
				
			|||||||
        class="material-input"
 | 
					        class="material-input"
 | 
				
			||||||
        @focus="handleMdFocus"
 | 
					        @focus="handleMdFocus"
 | 
				
			||||||
        @blur="handleMdBlur"
 | 
					        @blur="handleMdBlur"
 | 
				
			||||||
        @input="handleModelInput">
 | 
					        @input="handleModelInput"
 | 
				
			||||||
      <span class="material-input-bar"/>
 | 
					      >
 | 
				
			||||||
 | 
					      <span class="material-input-bar" />
 | 
				
			||||||
      <label class="material-label">
 | 
					      <label class="material-label">
 | 
				
			||||||
        <slot/>
 | 
					        <slot />
 | 
				
			||||||
      </label>
 | 
					      </label>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
@@ -191,7 +197,7 @@ export default {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style rel="stylesheet/scss" lang="scss" scoped>
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
  // Fonts:
 | 
					  // Fonts:
 | 
				
			||||||
  $font-size-base: 16px;
 | 
					  $font-size-base: 16px;
 | 
				
			||||||
  $font-size-small: 18px;
 | 
					  $font-size-small: 18px;
 | 
				
			||||||
 
 | 
				
			|||||||