Compare commits

..

1 Commits

Author SHA1 Message Date
Pan
54ac74e14d [release] 3.0.0 2017-12-05 11:16:29 +08:00
400 changed files with 13312 additions and 14535 deletions

10
.babelrc Normal file
View File

@@ -0,0 +1,10 @@
{
"presets": [
["env", {
"modules": false
}],
"stage-2"
],
"plugins": ["transform-runtime"],
"comments": false
}

View File

@@ -1,14 +0,0 @@
# 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

View File

@@ -1,6 +0,0 @@
# just a flag
ENV = 'production'
# base api
VUE_APP_BASE_API = '/prod-api'

View File

@@ -1,8 +0,0 @@
NODE_ENV = production
# just a flag
ENV = 'staging'
# base api
VUE_APP_BASE_API = '/stage-api'

View File

@@ -1,4 +1,3 @@
build/*.js
config/*.js
src/assets
public
dist

View File

@@ -1,198 +1,144 @@
module.exports = {
root: true,
parserOptions: {
root: true,
parser: 'babel-eslint',
sourceType: 'module'
},
env: {
browser: true,
node: true,
es6: true,
},
extends: ['plugin:vue/recommended', 'eslint:recommended'],
// add your custom rules here
//it is base on https://github.com/vuejs/eslint-config-vue
rules: {
"vue/max-attributes-per-line": [2, {
"singleline": 10,
"multiline": {
"max": 1,
"allowFirstLine": false
}
}],
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline":"off",
"vue/name-property-casing": ["error", "PascalCase"],
"vue/no-v-html": "off",
'accessor-pairs': 2,
'arrow-spacing': [2, {
'before': true,
'after': true
}],
'block-spacing': [2, 'always'],
'brace-style': [2, '1tbs', {
'allowSingleLine': true
}],
'camelcase': [0, {
'properties': 'always'
}],
'comma-dangle': [2, 'never'],
'comma-spacing': [2, {
'before': false,
'after': true
}],
'comma-style': [2, 'last'],
'constructor-super': 2,
'curly': [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
'eqeqeq': ["error", "always", {"null": "ignore"}],
'generator-star-spacing': [2, {
'before': true,
'after': true
}],
'handle-callback-err': [2, '^(err|error)$'],
'indent': [2, 2, {
'SwitchCase': 1
}],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [2, {
'beforeColon': false,
'afterColon': true
}],
'keyword-spacing': [2, {
'before': true,
'after': true
}],
'new-cap': [2, {
'newIsCap': true,
'capIsNew': false
}],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [2, {
'allowLoop': false,
'allowSwitch': false
}],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [2, {
'max': 1
}],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [2, {
'defaultAssignment': false
}],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [2, {
'vars': 'all',
'args': 'none'
}],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [2, {
'initialized': 'never'
}],
'operator-linebreak': [2, 'after', {
'overrides': {
'?': 'before',
':': 'before'
}
}],
'padded-blocks': [2, 'never'],
'quotes': [2, 'single', {
'avoidEscape': true,
'allowTemplateLiterals': true
}],
'semi': [2, 'never'],
'semi-spacing': [2, {
'before': false,
'after': true
}],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [2, {
'words': true,
'nonwords': false
}],
'spaced-comment': [2, 'always', {
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
}],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
'yoda': [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [2, 'always', {
objectsInObjects: false
}],
'array-bracket-spacing': [2, 'never']
}
parserOptions: {
sourceType: 'module'
},
env: {
browser: true,
node: true,
es6: true,
},
extends: 'eslint:recommended',
// required to lint *.vue files
plugins: [
'html'
],
// check if imports actually resolve
'settings': {
'import/resolver': {
'webpack': {
'config': 'build/webpack.base.conf.js'
}
}
},
// add your custom rules here
//it is base on https://github.com/vuejs/eslint-config-vue
'rules': {
'accessor-pairs': 2,
'arrow-spacing': [2, { 'before': true, 'after': true }],
'block-spacing': [2, 'always'],
'brace-style': [2, '1tbs', { 'allowSingleLine': true }],
'camelcase': [0, { 'properties': 'always' }],
'comma-dangle': [2, 'never'],
'comma-spacing': [2, { 'before': false, 'after': true }],
'comma-style': [2, 'last'],
'constructor-super': 2,
'curly': [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
'eqeqeq': [2, 'allow-null'],
'generator-star-spacing': [2, { 'before': true, 'after': true }],
'handle-callback-err': [2, '^(err|error)$' ],
'indent': [2, 2, { 'SwitchCase': 1 }],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [2, { 'beforeColon': false, 'afterColon': true }],
'keyword-spacing': [2, { 'before': true, 'after': true }],
'new-cap': [2, { 'newIsCap': true, 'capIsNew': false }],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [2, { 'allowLoop': false, 'allowSwitch': false }],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [2, { 'max': 1 }],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [2, { 'defaultAssignment': false }],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [2, { 'vars': 'all', 'args': 'none' }],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [2, { 'initialized': 'never' }],
'operator-linebreak': [2, 'after', { 'overrides': { '?': 'before', ':': 'before' } }],
'padded-blocks': [2, 'never'],
'quotes': [2, 'single', { 'avoidEscape': true, 'allowTemplateLiterals': true }],
'semi': [2, 'never'],
'semi-spacing': [2, { 'before': false, 'after': true }],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [2, { 'words': true, 'nonwords': false }],
'spaced-comment': [2, 'always', { 'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] }],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
'yoda': [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [2, 'always', { objectsInObjects: false }],
'array-bracket-spacing': [2, 'never']
}
}

View File

@@ -1,33 +0,0 @@
---
name: Bug report报告问题
about: Create a report to help us improve
---
<!--
注意:为更好的解决你的问题,请参考模板提供完整信息,准确描述问题,信息不全的 issue 将被关闭。
Note: In order to better solve your problem, please refer to the template to provide complete information, accurately describe the problem, and the incomplete information issue will be closed.
-->
## Bug report问题描述
#### Steps to reproduce问题复现步骤
<!--
1. [xxx]
2. [xxx]
3. [xxxx]
-->
#### Screenshot or Gif截图或动态图
#### Link to minimal reproduction最小可在线还原demo
<!--
Please only use Codepen, JSFiddle, CodeSandbox or a github repo
-->
#### Other relevant information格外信息
- Your OS:
- Node.js version:
- vue-element-admin version:

View File

@@ -1,7 +0,0 @@
---
name: Feature Request新功能建议
about: Suggest an idea for this project
---
## Feature request新功能建议

View File

@@ -1,14 +0,0 @@
---
name: Question提问
about: Asking questions about use
---
## Question提问
<!--
提问之前,请确定你已经过自己的努力,尝试解决过这个问题。
若是代码相关问题,请不要只截图,请提供在线 demo以便节约彼此的时间。
Before asking a question, please make sure that you have tried your best to solve this problem.
If it's a code-related issue, please don't just take screenshots. Please provide an online demo to save each other's time.
-->

21
.gitignore vendored
View File

@@ -1,23 +1,10 @@
.DS_Store
node_modules/
dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
**/*.log
tests/**/coverage/
tests/e2e/reports
gifs/
npm-debug.log
test/unit/coverage
test/e2e/reports
selenium-debug.log
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.local
package-lock.json
yarn.lock

View File

@@ -1,5 +0,0 @@
language: node_js
node_js: stable
script: npm run test
notifications:
email: false

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2017-present PanJiaChen
Copyright (c) 2017 PanJiaChen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

177
README-en.md Normal file
View File

@@ -0,0 +1,177 @@
[![vue](https://img.shields.io/badge/vue-2.4.2-brightgreen.svg)](https://github.com/vuejs/vue)
[![element-ui](https://img.shields.io/badge/element--ui-1.4.2-brightgreen.svg)](https://github.com/ElemeFE/element)
[![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg)]()
## Intro
> In the past half year, I have been building a backend for management dashboard using Vue. Though the backend has contained greater than 70 pages and over 10 permissions, it still takes insignificant effort to maintain the project. So I decide to make it open source so as to share my development experience and progress on backend. The tech stack is mainly [Vue.js](https://github.com/vuejs/vue)+[Element](https://github.com/ElemeFE/element)+[axios](https://github.com/mzabriskie/axios). Since it's a personal project, all data requests are simulated with [Mock.js](https://github.com/nuysoft/Mock). **Note:** if anyone wants to modify or develop based on this project, please remove the mock files.
**Live demo:** http://panjiachen.github.io/vue-element-admin
**Note: element-ui@1.4.2 is used in the project, so vue 2.3.0+ is required.**
- vueAdmin-template: [vueAdmin-template](https://github.com/PanJiaChen/vueAdmin-template)  
- electron-vue-admin: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
- Donate:[donate](https://github.com/PanJiaChen/vue-element-admin/blob/master/README-en.md#donate)
## Features
- Login/Logout
- Permission authentication
- Sidebar
- Breadcrumb
- Rich text editor
- Markdown editor
- JSON editor
- Drag & drop list
- SplitPane
- Dropzone
- Sticky
- CountTo
- ECharts
- 401, 404 error page
- Error log
- Export Excel
- Upload Excel
- Export Zip
- Table example
- Interactive table example
- Drag & drop table example
- Form example
- Multi-environments distribution
- Dashboard
- Two-factor authentication
- Collapsing sidebar (support nested routes)
- Mock data
- cache tabs example
- screenfull
- markdown2html
- views-tab
- clipboard
## Development
```bash
# Clone project
git clone https://github.com/PanJiaChen/vue-element-admin.git
# Install dependencies
npm install
# Or (not recommended for cnpm due to unknown bugs, use taobao mirror instead)
npm install --registry=https://registry.npm.taobao.org
# Run local dev server
npm run dev
```
Visit in browser: http://localhost:9527
## Distribution
```bash
# Build staged environment with webpack-bundle-analyzer
npm run build:sit-preview
# Build production environment
npm run build:prod
```
## Directory structure
```
├── build // build 
├── config // config
├── src // source code
│   ├── api // all requests
│   ├── assets // static resource like themes, fonts
│   ├── components // global public components
│   ├── directive // global directive
│   ├── filters // global filters
│   ├── mock // mock data
│   ├── router // router
│   ├── store // global status management
│   ├── styles // global styles
│   ├── utils // global public functions
│   ├── view // view
│   ├── App.vue // entry view
│   └── main.js // entry for loading components, initialization
├── static // third-party libraries not packed with Webpack
│   └── Tinymce // rich text
├── .babelrc // babel-loader config
├── eslintrc.js // eslint config
├── .gitignore // gitignore
├── favicon.ico // favicon
├── index.html // html template
└── package.json // package.json
```
## Changelog
Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases).
## Donate
If you find this project useful, you can buy me a cup of coffee
![donate](https://panjiachen.github.io/donate/donation.png)
## State Management
Only status of user and app configuration is managed by Vuex. Other data are managed by their own business pages.
## Demo
#### Two-factor authentication, supporting WeChat and QQ
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/2login.gif)
#### Realtime switching themes
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/theme.gif)
#### tabs
![tabs](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/tabs.gif)<br />
#### Collapsing sidebar
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/leftmenu.gif)
#### Drag & drop table
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/order.gif)
#### Interactive table
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/dynamictable.gif)
#### Uploading cropped avatar
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/uploadAvatar.gif)
#### Error log
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/errorlog.gif)
#### Rich text (integrated with Qiniu, watermark and customization)
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/editor.gif)
#### Packaging table component
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/table.gif)
#### Charts
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/echarts.gif)
#### Exporting to Excel
![](https://github.com/PanJiaChen/vue-element-admin/blob/master/gifs/excel.png)
#### More
http://panjiachen.github.io/vue-element-admin
## License
MIT

281
README.md
View File

@@ -2,213 +2,164 @@
<img width="320" src="https://wpimg.wallstcn.com/ecc53a42-d79b-42e2-8852-5126b810a4c8.svg">
</p>
<p align="center">
<a href="https://github.com/vuejs/vue">
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
</a>
<a href="https://github.com/ElemeFE/element">
<img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
</a>
<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">
</a>
<a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
</a>
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
</a>
<a href="https://gitter.im/vue-element-admin/discuss">
<img src="https://badges.gitter.im/Join%20Chat.svg" alt="gitter">
</a>
<a href="https://panjiachen.github.io/vue-element-admin-site/donate">
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
</a>
</p>
# vue-element-admin
English | [简体中文](./README.zh-CN.md)
[![vue](https://img.shields.io/badge/vue-2.5.9-brightgreen.svg)](https://github.com/vuejs/vue)
[![element-ui](https://img.shields.io/badge/element--ui-2.0.7-brightgreen.svg)](https://github.com/ElemeFE/element)
[![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg)]()
## Introduction
**A magical vue admin.**
[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).
- [线上地址](http://panjiachen.github.io/vue-element-admin)
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.
- [使用文档](https://panjiachen.github.io/vue-element-admin-site/#/)
- [Preview](http://panjiachen.github.io/vue-element-admin)
- [English Document](https://github.com/PanJiaChen/vue-element-admin/blob/master/README-en.md)
- [Documentation](https://panjiachen.github.io/vue-element-admin-site/)
- [wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
- [Gitter](https://gitter.im/vue-element-admin/discuss)
- [donate](https://panjiachen.github.io/vue-element-admin-site/#/donate)
- [Donate](https://panjiachen.github.io/vue-element-admin-site/donate/)
**本项目的定位是后台集成方案,不适合当基础模板来开发。**
- 模板建议使用: [vueAdmin-template](https://github.com/PanJiaChen/vueAdmin-template)  
- 桌面端: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 国内用户可访问该地址在线预览
**注意该项目目前使用element-ui@2.0.5版本,所以最低兼容 Vue 2.5.0**
- 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)
- Typescript: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
楼主这里有一份调查[问卷](https://www.wjx.cn/m/16866569.aspx) 有空请填写一下,以表对本项目的支持~ps:不是给这个调查问卷网站做广告,所以填完问卷不用点上面抽奖有的没的那些东西
**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)**
## 前序准备
**This project does not support low version browsers (e.g. IE). Please add polyfill by yourself.**
你的本地环境需要安装 [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/) 和 [element-ui](https://github.com/ElemeFE/element),提前了解和学习这些知识会对使用本项目有很大的帮助。
## Preparation
同时配套一个系列的教程文章,如何从零构建后一个完整的后台项目,建议大家先看完这些文章再来实践本项目
- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
- [手摸手,带你优雅的使用 icon](https://juejin.im/post/59bb864b5188257e7a427c09)
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.
相应需求开了一个qq群 `591724180` 方便大家交流
<p align="center">
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
</p>
或者可以加入该 **[圈子](https://jianshiapp.com/circles/1209)** 讨论问题
## Sponsors
**如有问题请先看上述使用文档和文章,若不能满足,欢迎 issue 和 pr**
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>
**该项目不支持低版本游览器(如ie)有需求请自行添加polyfill [详情](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)**
## Features
```
- Login / Logout
- Permission Authentication
- Page permission
- Directive permission
- Permission configuration page
- Two-step login
- Multi-environment build
- dev sit stage prod
- Global Features
- I18n
- Multiple dynamic themes
- Dynamic sidebar (supports multi-level routing)
- Dynamic breadcrumb
- Tags-view (Tab page Support right-click operation)
- Svg Sprite
- Mock data
- Screenfull
- Responsive Sidebar
- Editor
- Rich Text Editor
- Markdown Editor
- JSON Editor
- Excel
- Export Excel
- Upload Excel
- Visualization Excel
- Export zip
- Table
- Dynamic Table
- Drag And Drop Table
- Inline Edit Table
- Error Page
- 401
- 404
- Components
- Avatar Upload
- Back To Top
- Drag Dialog
- Drag Select
- Drag Kanban
- Drag List
- SplitPane
- Dropzone
- Sticky
- CountTo
- Advanced Example
- Error Log
## 功能
- 登录/注销
- 权限验证
- 多环境发布
- 动态侧边栏(支持多级路由)
- 动态面包屑
- 国际化多语言
- 多种动态换肤
- 快捷导航(标签页)
- 富文本编辑器
- Markdown编辑器
- JSON编辑器
- Screenfull全屏
- 列表拖拽
- Svg Sprite 图标
- Dashboard
- Guide Page
- ECharts
- Clipboard
- Markdown to html
```
- 本地mock数据
- Echarts 图表
- Clipboard(剪贴复制)
- 401/404错误页面
- 错误日志
- 导出excel
- 导出zip
- 前端可视化excel
- Table example
- 动态table example
- 拖拽table example
- 内联编辑table example
- Form example
- 二步登录
- SplitPane
- Dropzone
- Sticky
- CountTo
- Markdown2html
## Getting started
## 开发
```bash
# 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
# 安装依赖
npm install
   
//or # 建议不要用cnpm  安装有各种诡异的bug 可以通过如下操作解决npm速度慢的问题
npm install --registry=https://registry.npm.taobao.org
# install dependency
npm install
# develop
npm run dev
# 本地开发 开启服务
npm run dev
```
浏览器访问 http://localhost:9527
This will automatically open http://localhost:9527
## Build
## 发布
```bash
# build for test environment
npm run build:stage
# 发布测试环境 带webpack ananalyzer
npm run build:sit-preview
# build for production environment
npm run build:prod
# 构建生成环境
npm run build:prod
```
## Advanced
更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/#/)
```bash
# preview the release environment effect
npm run preview
## 目录结构
```shell
├── build // 构建相关  
├── config // 配置相关
├── src // 源代码
│   ├── api // 所有请求
│   ├── assets // 主题 字体等静态资源
│   ├── components // 全局公用组件
│   ├── directive // 全局指令
│   ├── filtres // 全局 filter
│   ├── icons // 项目所有 svg icons
│   ├── lang // 国际化 language
│   ├── mock // 项目mock 模拟数据
│   ├── router // 路由
│   ├── store // 全局 store管理
│   ├── styles // 全局样式
│   ├── utils // 全局公用方法
│   ├── vendor // 公用vendor
│   ├── views // view
│   ├── App.vue // 入口页面
│   ├── main.js // 入口 加载组件 初始化等
│ └── permission.js // 权限管理
├── static // 第三方不打包资源
│   └── Tinymce // 富文本
├── .babelrc // babel-loader 配置
├── eslintrc.js // eslint 配置项
├── .gitignore // git 忽略项
├── favicon.ico // favicon图标
├── index.html // html模板
└── package.json // package.json
# preview the release environment effect + static resource analysis
npm run preview -- --report
# code format check
npm run lint
# code format check and auto fix
npm run lint -- --fix
```
Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information
## Changelog
Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases).
## Online Demo
[Preview](http://panjiachen.github.io/vue-element-admin)
## [查看更多demo](http://panjiachen.github.io/vue-element-admin)
![](https://wpimg.wallstcn.com/1bc334a6-32a8-4f29-a037-ac3f5ce32588.png)
## Donate
If you find this project useful, you can buy author a glass of juice :tropical_drink:
![donate](https://wpimg.wallstcn.com/bd273f0d-83a0-4ef2-92e1-9ac8ed3746b9.png)
[Paypal Me](https://www.paypal.me/panfree23)
[Buy me a coffee](https://www.buymeacoffee.com/Pan)
## Browsers support
Modern browsers and Internet Explorer 10+.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| --------- | --------- | --------- | --------- |
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
If you find this project useful, you can buy me a cup of coffee
![donate](https://panjiachen.github.io/donate/donation.png)
## License
[MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
Copyright (c) 2017-present PanJiaChen
MIT

View File

@@ -1,232 +0,0 @@
<p align="center">
<img width="320" src="https://wpimg.wallstcn.com/ecc53a42-d79b-42e2-8852-5126b810a4c8.svg">
</p>
<p align="center">
<a href="https://github.com/vuejs/vue">
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
</a>
<a href="https://github.com/ElemeFE/element">
<img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
</a>
<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">
</a>
<a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
</a>
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
</a>
<a href="https://gitter.im/vue-element-admin/discuss">
<img src="https://badges.gitter.im/Join%20Chat.svg" alt="gitter">
</a>
<a href="https://panjiachen.gitee.io/vue-element-admin-site/zh/donate">
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
</a>
</p>
简体中文 | [English](./README.md)
## 简介
[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)
- [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
- [Gitter 讨论组](https://gitter.im/vue-element-admin/discuss)
- [Donate](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate)
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
- [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)
- 桌面端: [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))
**目前版本为 `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)**
**该项目不支持低版本浏览器(如 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/) 、[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/591aa14f570c35006961acac)
- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
- [手摸手,带你优雅的使用 icon](https://juejin.im/post/59bb864b5188257e7a427c09)
- [手摸手,带你用合理的姿势使用 webpack4](https://juejin.im/post/5b56909a518825195f499806)
- [手摸手,带你用合理的姿势使用 webpack4](https://juejin.im/post/5b5d6d6f6fb9a04fea58aabc)
**如有问题请先看上述使用文档和文章,若不能满足,欢迎 issue 和 pr**
<p align="center">
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
</p>
## 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)
<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>
## 功能
```
- 登录 / 注销
- 权限验证
- 页面权限
- 指令权限
- 权限配置
- 二步登录
- 多环境发布
- dev sit stage prod
- 全局功能
- 国际化多语言
- 多种动态换肤
- 动态侧边栏(支持多级路由嵌套)
- 动态面包屑
- 快捷导航(标签页)
- Svg Sprite 图标
- 本地/后端 mock 数据
- Screenfull全屏
- 自适应收缩侧边栏
- 编辑器
- 富文本
- Markdown
- JSON 等多格式
- Excel
- 导出excel
- 导入excel
- 前端可视化excel
- 导出zip
- 表格
- 动态表格
- 拖拽表格
- 内联编辑
- 错误页面
- 401
- 404
- 組件
- 头像上传
- 返回顶部
- 拖拽Dialog
- 拖拽Select
- 拖拽看板
- 列表拖拽
- SplitPane
- Dropzone
- Sticky
- CountTo
- 综合实例
- 错误日志
- Dashboard
- 引导页
- ECharts 图表
- Clipboard(剪贴复制)
- Markdown2html
```
## 开发
```bash
# 克隆项目
git clone https://github.com/PanJiaChen/vue-element-admin.git
# 进入项目目录
cd vue-element-admin
# 安装依赖
npm install
# 建议不要用 cnpm 安装 会有各种诡异的bug 可以通过如下操作解决 npm 下载速度慢的问题
npm install --registry=https://registry.npm.taobao.org
# 启动服务
npm run dev
```
浏览器访问 http://localhost:9527
## 发布
```bash
# 构建测试环境
npm run build:stage
# 构建生产环境
npm run build:prod
```
## 其它
```bash
# 预览发布环境效果
npm run preview
# 预览发布环境效果 + 静态资源分析
npm run preview -- --report
# 代码格式检查
npm run lint
# 代码格式检查并自动修复
npm run lint -- --fix
```
更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
## Changelog
Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases).
## Online Demo
[在线 Demo](http://panjiachen.github.io/vue-element-admin)
## Donate
如果你觉得这个项目帮助到了你,你可以帮作者买一杯果汁表示鼓励 :tropical_drink:
![donate](https://panjiachen.github.io/donate/donation.png)
[更多捐赠方式](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate)
[Paypal Me](https://www.paypal.me/panfree23)
[Buy me a coffee](https://www.buymeacoffee.com/Pan)
## Browsers support
Modern browsers and Internet Explorer 10+.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| --------- | --------- | --------- | --------- |
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
## License
[MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
Copyright (c) 2017-present PanJiaChen

View File

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

39
build/build.js Normal file
View File

@@ -0,0 +1,39 @@
require('./check-versions')();
var server = require('pushstate-server');
var opn = require('opn')
var ora = require('ora')
var rm = require('rimraf')
var path = require('path')
var chalk = require('chalk')
var webpack = require('webpack');
var config = require('../config');
var webpackConfig = require('./webpack.prod.conf');
var spinner = ora('building for ' + process.env.NODE_ENV + ' of ' + process.env.env_config+ ' mode...' )
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, function (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')
console.log(chalk.cyan(' Build complete.\n'))
if(process.env.npm_config_preview){
server.start({
port: 9528,
directory: './dist',
file: '/index.html'
});
console.log('> Listening at ' + 'http://localhost:9528' + '\n')
}
})
})

45
build/check-versions.js Normal file
View File

@@ -0,0 +1,45 @@
var chalk = require('chalk')
var semver = require('semver')
var packageConfig = require('../package.json')
function exec(cmd) {
return require('child_process').execSync(cmd).toString().trim()
}
var versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
},
{
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
}
]
module.exports = function () {
var warnings = []
for (var i = 0; i < versionRequirements.length; i++) {
var 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 (var i = 0; i < warnings.length; i++) {
var warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}

9
build/dev-client.js Normal file
View File

@@ -0,0 +1,9 @@
/* eslint-disable */
require('eventsource-polyfill')
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
hotClient.subscribe(function (event) {
if (event.action === 'reload') {
window.location.reload()
}
})

93
build/dev-server.js Normal file
View File

@@ -0,0 +1,93 @@
require('./check-versions')(); // 检查 Node 和 npm 版本
var config = require('../config');
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}
var opn = require('opn')
var path = require('path');
var express = require('express');
var webpack = require('webpack');
var proxyMiddleware = require('http-proxy-middleware');
var webpackConfig = require('./webpack.dev.conf');
// default port where dev server listens for incoming traffic
var port = process.env.PORT || config.dev.port;
// automatically open browser, if not set will be false
var autoOpenBrowser = !!config.dev.autoOpenBrowser;
// Define HTTP proxies to your custom API backend
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable;
var app = express();
var compiler = webpack(webpackConfig);
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: true
});
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: false,
heartbeat: 2000
});
// force page reload when html-webpack-plugin template changes
// currently disabled until this is resolved:
// https://github.com/jantimon/html-webpack-plugin/issues/680
// compiler.plugin('compilation', function (compilation) {
// compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
// hotMiddleware.publish({ action: 'reload' })
// cb()
// })
// })
// proxy api requests
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === 'string') {
options = {target: options}
}
app.use(proxyMiddleware(options.filter || context, options))
});
// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')());
// serve webpack bundle output
app.use(devMiddleware);
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware);
// serve pure static assets
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory);
app.use(staticPath, express.static('./static'));
var uri = 'http://localhost:' + port
var _resolve
var readyPromise = new Promise(resolve => {
_resolve = resolve
})
console.log('> Starting dev server...')
devMiddleware.waitUntilValid(() => {
console.log('> Listening at ' + uri + '\n')
// when env is testing, don't need open it
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri)
}
_resolve()
})
var server = app.listen(port)
module.exports = {
ready: readyPromise,
close: () => {
server.close()
}
}

View File

@@ -1,35 +0,0 @@
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}`)
}

78
build/utils.js Normal file
View File

@@ -0,0 +1,78 @@
var path = require('path')
var config = require('../config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
exports.assetsPath = function (_path) {
var assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
var cssLoader = {
loader: 'css-loader',
options: {
minimize: process.env.NODE_ENV === 'production',
sourceMap: options.sourceMap
}
}
var postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: true
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
var loaders = options.usePostCSS !== false ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(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) {
var output = []
var loaders = exports.cssLoaders(options)
for (var extension in loaders) {
var loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}

12
build/vue-loader.conf.js Normal file
View File

@@ -0,0 +1,12 @@
var utils = require('./utils')
var config = require('../config')
var isProduction = process.env.NODE_ENV === 'production'
module.exports = {
loaders: utils.cssLoaders({
sourceMap: isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap,
extract: isProduction
})
}

View File

@@ -0,0 +1,92 @@
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
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: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'src': path.resolve(__dirname, '../src'),
'assets': path.resolve(__dirname, '../src/assets'),
'components': path.resolve(__dirname, '../src/components'),
'views': path.resolve(__dirname, '../src/views'),
'styles': path.resolve(__dirname, '../src/styles'),
'api': path.resolve(__dirname, '../src/api'),
'utils': path.resolve(__dirname, '../src/utils'),
'store': path.resolve(__dirname, '../src/store'),
'router': path.resolve(__dirname, '../src/router'),
'mock': path.resolve(__dirname, '../src/mock'),
'vendor': path.resolve(__dirname, '../src/vendor'),
'static': path.resolve(__dirname, '../static')
}
},
module: {
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: "pre",
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader?cacheDirectory',
include: [resolve('src'), resolve('test')]
},
{
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: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
//注入全局mixin
// sassResources: path.join(__dirname, '../src/styles/mixin.scss'),
// sassLoader: {
// data: path.join(__dirname, '../src/styles/index.scss')
// },
}

44
build/webpack.dev.conf.js Normal file
View File

@@ -0,0 +1,44 @@
var utils = require('./utils')
var path = require('path')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})
function resolveApp(relativePath) {
return path.resolve(relativePath);
}
module.exports = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-source-map is faster for development
devtool: '#cheap-source-map',
cache: true,
plugins: [
new webpack.DefinePlugin({
'process.env': config.dev.env
}),
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
favicon: resolveApp('favicon.ico'),
inject: true,
path: config.dev.assetsPublicPath + config.dev.assetsSubDirectory
}),
new FriendlyErrorsPlugin()
]
})

141
build/webpack.prod.conf.js Normal file
View File

@@ -0,0 +1,141 @@
var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var CopyWebpackPlugin = require('copy-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
var env = config.build[process.env.env_config+'Env']
function resolveApp(relativePath) {
return path.resolve(relativePath);
}
var webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? '#source-map' : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'),
publicPath: config.build.assetsPublicPath
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css')
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin(),
// 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: 'index.html',
template: 'index.html',
inject: true,
favicon: resolveApp('favicon.ico'),
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true
},
path: config.build.assetsPublicPath + config.build.assetsSubDirectory,
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// cache Module Identifiers
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// split echarts into its own file
new webpack.optimize.CommonsChunkPlugin({
async: 'echarts',
minChunks(module) {
var context = module.context;
return context && (context.indexOf('echarts') >= 0 || context.indexOf('zrender') >= 0);
}
}),
// split xlsx into its own file
new webpack.optimize.CommonsChunkPlugin({
async: 'xlsx',
minChunks(module) {
var context = module.context;
return context && (context.indexOf('xlsx') >= 0);
}
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}])
]
})
if (config.build.bundleAnalyzerReport) {
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig

6
config/dev.env.js Normal file
View File

@@ -0,0 +1,6 @@
module.exports = {
NODE_ENV: '"development"',
ENV_CONFIG: '"dev"',
BASE_API: '"https://api-dev"',
APP_ORIGIN: '"https://wallstreetcn.com"'
}

39
config/index.js Normal file
View File

@@ -0,0 +1,39 @@
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')
module.exports = {
build: {
sitEnv: require('./sit.env'),
prodEnv: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: './', //请根据自己路径配置更改
productionSourceMap: false,
// 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 --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
},
dev: {
env: require('./dev.env'),
port: 9527,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// 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
}
}

6
config/prod.env.js Normal file
View File

@@ -0,0 +1,6 @@
module.exports = {
NODE_ENV: '"production"',
ENV_CONFIG: '"prod"',
BASE_API: '"https://api-prod"',
APP_ORIGIN: '"https://wallstreetcn.com"'
};

6
config/sit.env.js Normal file
View File

@@ -0,0 +1,6 @@
module.exports = {
NODE_ENV: '"production"',
ENV_CONFIG: '"sit"',
BASE_API: '"https://api-sit"',
APP_ORIGIN: '"https://wallstreetcn.com"'
};

View File

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

BIN
gifs/2login.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

BIN
gifs/dynamictable.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
gifs/echarts.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

BIN
gifs/editor.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 KiB

BIN
gifs/errorlog.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 KiB

BIN
gifs/excel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
gifs/leftmenu.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 KiB

BIN
gifs/login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
gifs/order.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
gifs/table.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

BIN
gifs/tabs.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
gifs/theme.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

BIN
gifs/upload1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

BIN
gifs/uploadAvatar.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

15
index.html Normal file
View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>vue-element-admin</title>
</head>
<script src=<%= htmlWebpackPlugin.options.path %>/tinymce/tinymce.min.js></script>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@@ -1,27 +0,0 @@
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/'
}

View File

@@ -1,116 +0,0 @@
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'
}
}
}
]

View File

@@ -1,70 +0,0 @@
import Mock from 'mockjs'
import { param2Obj } from '../src/utils'
import user from './user'
import role from './role'
import article from './article'
import search from './remoteSearch'
const mocks = [
...user,
...role,
...article,
...search
]
// for front mock
// please use it cautiously, it will redefine XMLHttpRequest,
// which will cause many of your third-party libraries to be invalidated(like progress event).
export function mockXHR() {
// mock patch
// 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))
}
}
// for mock server
const responseFake = (url, type, respond) => {
return {
url: new RegExp(`/mock${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)
})

View File

@@ -1,62 +0,0 @@
const chokidar = require('chokidar')
const bodyParser = require('body-parser')
const chalk = require('chalk')
function registerRoutes(app) {
let mockStartIndex
const { default: mocks } = require('./index.js')
for (const mock of mocks) {
app[mock.type](mock.url, mock.response)
mockStartIndex = app._router.stack.length
}
const mockRoutesLength = Object.keys(mocks).length
return {
mockRoutesLength: mockRoutesLength,
mockStartIndex: mockStartIndex - mockRoutesLength
}
}
function unregisterRoutes() {
Object.keys(require.cache).forEach(i => {
if (i.includes('/mock')) {
delete require.cache[require.resolve(i)]
}
})
}
module.exports = app => {
// es6 polyfill
require('@babel/register')
// parse app.body
// http://expressjs.com/en/4x/api.html#req.body
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: true
}))
const mockRoutes = registerRoutes(app)
var mockRoutesLength = mockRoutes.mockRoutesLength
var mockStartIndex = mockRoutes.mockStartIndex
// watch files, hot reload mock server
chokidar.watch(('./mock'), {
ignored: 'mock/mock-server.js',
persistent: true,
ignoreInitial: true
}).on('all', (event, path) => {
if (event === 'change' || event === 'add') {
// remove mock routes stack
app._router.stack.splice(mockStartIndex, mockRoutesLength)
// clear routes cache
unregisterRoutes()
const mockRoutes = registerRoutes(app)
mockRoutesLength = mockRoutes.mockRoutesLength
mockStartIndex = mockRoutes.mockStartIndex
console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
}
})
}

View File

@@ -1,51 +0,0 @@
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']
}]
}
}
}
}
]

View File

@@ -1,98 +0,0 @@
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'
}
}
}
]

View File

@@ -1,525 +0,0 @@
// 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 }
]

View File

@@ -1,84 +0,0 @@
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'
}
}
}
]

View File

@@ -1,109 +1,98 @@
{
"name": "vue-element-admin",
"version": "4.0.1",
"description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features",
"version": "3.1.0",
"description": "A Vue.js admin",
"author": "Pan <panfree23@gmail.com>",
"license": "MIT",
"private": true,
"scripts": {
"dev": "vue-cli-service serve",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview",
"lint": "eslint --ext .js,.vue src",
"test:unit": "vue-cli-service test:unit",
"test:ci": "npm run lint && npm run test:unit",
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
"new": "plop"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
},
"keywords": [
"vue",
"admin",
"dashboard",
"element-ui",
"boilerplate",
"admin-template",
"management-system"
],
"repository": {
"type": "git",
"url": "git+https://github.com/PanJiaChen/vue-element-admin.git"
},
"bugs": {
"url": "https://github.com/PanJiaChen/vue-element-admin/issues"
"dev": "node build/dev-server.js",
"build:prod": "cross-env NODE_ENV=production env_config=prod node build/build.js",
"build:sit": "cross-env NODE_ENV=production env_config=sit node build/build.js",
"build:sit-preview": "cross-env NODE_ENV=production env_config=sit npm_config_preview=true npm_config_report=true node build/build.js",
"lint": "eslint --ext .js,.vue src"
},
"dependencies": {
"axios": "0.18.0",
"clipboard": "2.0.4",
"codemirror": "5.45.0",
"driver.js": "0.9.5",
"dropzone": "5.5.1",
"echarts": "4.2.1",
"element-ui": "2.7.0",
"file-saver": "2.0.1",
"fuse.js": "3.4.4",
"axios": "0.17.1",
"clipboard": "1.7.1",
"codemirror": "5.31.0",
"dropzone": "5.2.0",
"echarts": "3.8.5",
"element-ui": "2.0.7",
"file-saver": "1.3.3",
"font-awesome": "4.7.0",
"js-cookie": "2.2.0",
"jsonlint": "1.6.3",
"jszip": "3.2.1",
"jsonlint": "1.6.2",
"jszip": "3.1.4",
"mockjs": "1.0.1-beta3",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"screenfull": "4.2.0",
"showdown": "1.9.0",
"sortablejs": "1.8.4",
"tui-editor": "1.3.3",
"vue": "2.6.10",
"vue-count-to": "1.0.13",
"screenfull": "3.3.2",
"showdown": "1.8.2",
"simplemde": "1.11.2",
"sortablejs": "1.6.1",
"vue": "2.5.9",
"vue-count-to": "1.0.10",
"vue-i18n": "7.3.2",
"vue-router": "3.0.2",
"vue-splitpane": "1.0.4",
"vuedraggable": "2.20.0",
"vuex": "3.1.0",
"xlsx": "0.14.1"
"vue-multiselect": "2.0.6",
"vue-router": "3.0.1",
"vue-splitpane": "1.0.0",
"vuedraggable": "2.15.0",
"vuex": "3.0.1",
"xlsx": "^0.11.7"
},
"devDependencies": {
"@babel/core": "7.0.0",
"@babel/register": "7.0.0",
"@vue/cli-plugin-babel": "3.5.3",
"@vue/cli-plugin-eslint": "3.5.1",
"@vue/cli-plugin-unit-jest": "3.5.3",
"@vue/cli-service": "3.5.3",
"@vue/test-utils": "1.0.0-beta.29",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "10.0.1",
"babel-jest": "23.6.0",
"chalk": "2.4.2",
"chokidar": "2.1.5",
"connect": "3.6.6",
"eslint": "5.15.3",
"eslint-plugin-vue": "5.2.2",
"html-webpack-plugin": "3.2.0",
"husky": "1.3.1",
"lint-staged": "8.1.5",
"mockjs": "1.0.1-beta3",
"node-sass": "^4.9.0",
"plop": "2.3.0",
"runjs": "^4.3.2",
"sass-loader": "^7.1.0",
"script-ext-html-webpack-plugin": "2.1.3",
"autoprefixer": "7.1.6",
"babel-core": "6.26.0",
"babel-eslint": "8.0.2",
"babel-loader": "7.1.2",
"babel-plugin-transform-runtime": "6.23.0",
"babel-preset-env": "1.6.1",
"babel-preset-stage-2": "6.24.1",
"babel-register": "6.26.0",
"chalk": "2.3.0",
"connect-history-api-fallback": "1.4.0",
"copy-webpack-plugin": "4.2.0",
"cross-env": "5.1.1",
"css-loader": "0.28.7",
"eslint": "4.11.0",
"eslint-friendly-formatter": "3.0.0",
"eslint-import-resolver-webpack": "0.8.3",
"eslint-loader": "1.9.0",
"eslint-plugin-html": "3.2.2",
"eslint-plugin-import": "2.8.0",
"eventsource-polyfill": "0.9.6",
"express": "4.16.2",
"extract-text-webpack-plugin": "3.0.2",
"file-loader": "0.11.2",
"friendly-errors-webpack-plugin": "1.6.1",
"function-bind": "1.1.0",
"html-webpack-plugin": "2.30.0",
"http-proxy-middleware": "0.17.4",
"node-sass": "^4.5.0",
"opn": "4.0.2",
"optimize-css-assets-webpack-plugin": "3.2.0",
"ora": "1.1.0",
"postcss-loader": "^2.0.8",
"pushstate-server": "2.1.0",
"rimraf": "2.6.0",
"sass-loader": "6.0.6",
"script-loader": "0.7.2",
"serve-static": "^1.13.2",
"svg-sprite-loader": "4.1.3",
"svgo": "1.2.0",
"vue-template-compiler": "2.6.10"
"semver": "5.3.0",
"style-loader": "0.19.0",
"svg-sprite-loader": "3.4.1",
"url-loader": "0.6.2",
"vue-loader": "13.5.0",
"vue-style-loader": "3.0.3",
"vue-template-compiler": "2.5.9",
"webpack": "3.8.1",
"webpack-bundle-analyzer": "2.9.0",
"webpack-dev-middleware": "1.12.0",
"webpack-hot-middleware": "2.20.0",
"webpack-merge": "4.1.0"
},
"engines": {
"node": ">=8.9",
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [

View File

@@ -1,26 +0,0 @@
{{#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}}

View File

@@ -1,55 +0,0 @@
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
}
}

View File

@@ -1,9 +0,0 @@
exports.notEmpty = name => {
return v => {
if (!v || v.trim === '') {
return `${name} is required`
} else {
return true
}
}
}

View File

@@ -1,26 +0,0 @@
{{#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}}

View File

@@ -1,55 +0,0 @@
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
}
}

View File

@@ -1,7 +0,0 @@
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)
}

View File

@@ -1,16 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= webpackConfig.name %></title>
</head>
<body>
<script src="<%= BASE_URL %>static/tinymce4.7.5/tinymce.min.js"></script>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@@ -1,138 +0,0 @@
/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #a67f59;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

View File

@@ -1,154 +0,0 @@
.mce-visualblocks p {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background-image: url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7);
background-repeat: no-repeat;
}
.mce-visualblocks h1 {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==);
background-repeat: no-repeat;
}
.mce-visualblocks h2 {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==);
background-repeat: no-repeat;
}
.mce-visualblocks h3 {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7);
background-repeat: no-repeat;
}
.mce-visualblocks h4 {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==);
background-repeat: no-repeat;
}
.mce-visualblocks h5 {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==);
background-repeat: no-repeat;
}
.mce-visualblocks h6 {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==);
background-repeat: no-repeat;
}
.mce-visualblocks div:not([data-mce-bogus]) {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background-image: url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7);
background-repeat: no-repeat;
}
.mce-visualblocks section {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background-image: url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=);
background-repeat: no-repeat;
}
.mce-visualblocks article {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background-image: url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7);
background-repeat: no-repeat;
}
.mce-visualblocks blockquote {
padding-top: 10px;
border: 1px dashed #BBB;
background-image: url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7);
background-repeat: no-repeat;
}
.mce-visualblocks address {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background-image: url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=);
background-repeat: no-repeat;
}
.mce-visualblocks pre {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background-image: url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==);
background-repeat: no-repeat;
}
.mce-visualblocks figure {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background-image: url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7);
background-repeat: no-repeat;
}
.mce-visualblocks hgroup {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background-image: url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7);
background-repeat: no-repeat;
}
.mce-visualblocks aside {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background-image: url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=);
background-repeat: no-repeat;
}
.mce-visualblocks figcaption {
border: 1px dashed #BBB;
}
.mce-visualblocks ul {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background-image: url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==);
background-repeat: no-repeat;
}
.mce-visualblocks ol {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==);
background-repeat: no-repeat;
}
.mce-visualblocks dl {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==);
background-repeat: no-repeat;
}

View File

@@ -1 +0,0 @@
.word-wrap{word-wrap:break-word;-ms-word-break:break-all;word-break:break-all;word-break:break-word;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid rgba(208,2,27,0.5);cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#2276d2 !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2276d2}.mce-content-body *[data-mce-selected="inline-boundary"]{background:#bfe6ff}.mce-content-body .mce-item-anchor[data-mce-selected]{background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-content-body hr{cursor:default}.ephox-snooker-resizer-bar{background-color:#2276d2;opacity:0}.ephox-snooker-resizer-cols{cursor:col-resize}.ephox-snooker-resizer-rows{cursor:row-resize}.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity:.2}.mce-content-body{line-height:1.3}

View File

@@ -1 +0,0 @@
body{background-color:#FFFFFF;color:#000000;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px;line-height:1.3;scrollbar-3dlight-color:#F0F0EE;scrollbar-arrow-color:#676662;scrollbar-base-color:#F0F0EE;scrollbar-darkshadow-color:#DDDDDD;scrollbar-face-color:#E0E0DD;scrollbar-highlight-color:#F0F0EE;scrollbar-shadow-color:#F0F0EE;scrollbar-track-color:#F5F5F5}td,th{font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px}.word-wrap{word-wrap:break-word;-ms-word-break:break-all;word-break:break-all;word-break:break-word;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid rgba(208,2,27,0.5);cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#2276d2 !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2276d2}.mce-content-body *[data-mce-selected="inline-boundary"]{background:#bfe6ff}.mce-content-body .mce-item-anchor[data-mce-selected]{background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-content-body hr{cursor:default}.ephox-snooker-resizer-bar{background-color:#2276d2;opacity:0}.ephox-snooker-resizer-cols{cursor:col-resize}.ephox-snooker-resizer-rows{cursor:row-resize}.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity:.2} a {color: #1478F0;}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +1,16 @@
<template>
<div id="app">
<router-view />
</div>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
export default{
name: 'APP'
}
</script>
<style lang="scss">
@import '~normalize.css/normalize.css'; // normalize.css 样式格式化
@import './styles/index.scss'; // 全局自定义样式
</style>

View File

@@ -8,11 +8,10 @@ export function fetchList(query) {
})
}
export function fetchArticle(id) {
export function fetchArticle() {
return request({
url: '/article/detail',
method: 'get',
params: { id }
method: 'get'
})
}

View File

@@ -1,14 +1,25 @@
import request from '@/utils/request'
export function login(data) {
export function loginByUsername(username, password) {
const data = {
username,
password
}
return request({
url: '/user/login',
url: '/login/login',
method: 'post',
data
})
}
export function getInfo(token) {
export function logout() {
return request({
url: '/login/logout',
method: 'post'
})
}
export function getUserInfo(token) {
return request({
url: '/user/info',
method: 'get',
@@ -16,10 +27,3 @@ export function getInfo(token) {
})
}
export function logout() {
return request({
url: '/user/logout',
method: 'post'
})
}

View File

@@ -1,17 +1,9 @@
import request from '@/utils/request'
export function searchUser(name) {
export function userSearch(name) {
return request({
url: '/search/user',
method: 'get',
params: { name }
})
}
export function transactionList(query) {
return request({
url: '/transaction/list',
method: 'get',
params: query
})
}

View File

@@ -1,38 +0,0 @@
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'
})
}

9
src/api/transaction.js Normal file
View File

@@ -0,0 +1,9 @@
import request from '@/utils/request'
export function fetchList(query) {
return request({
url: '/transaction/list',
method: 'get',
params: query
})
}

View File

@@ -0,0 +1,199 @@
/* eslint-disable */
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['exports', 'echarts'], factory);
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
// CommonJS
factory(exports, require('echarts'));
} else {
// Browser globals
factory({}, root.echarts);
}
}(this, function (exports, echarts) {
var log = function (msg) {
if (typeof console !== 'undefined') {
console && console.error && console.error(msg);
}
};
if (!echarts) {
log('ECharts is not Loaded');
return;
}
var colorPalette = [
'#2ec7c9','#b6a2de','#5ab1ef','#ffb980','#d87a80',
'#8d98b3','#e5cf0d','#97b552','#95706d','#dc69aa',
'#07a2a4','#9a7fd1','#588dd5','#f5994e','#c05050',
'#59678c','#c9ab00','#7eb00a','#6f5553','#c14089'
];
var theme = {
color: colorPalette,
title: {
textStyle: {
fontWeight: 'normal',
color: '#008acd'
}
},
visualMap: {
itemWidth: 15,
color: ['#5ab1ef','#e0ffff']
},
toolbox: {
iconStyle: {
normal: {
borderColor: colorPalette[0]
}
}
},
tooltip: {
backgroundColor: 'rgba(50,50,50,0.5)',
axisPointer : {
type : 'line',
lineStyle : {
color: '#008acd'
},
crossStyle: {
color: '#008acd'
},
shadowStyle : {
color: 'rgba(200,200,200,0.2)'
}
}
},
dataZoom: {
dataBackgroundColor: '#efefff',
fillerColor: 'rgba(182,162,222,0.2)',
handleColor: '#008acd'
},
grid: {
borderColor: '#eee'
},
categoryAxis: {
axisLine: {
lineStyle: {
color: '#008acd'
}
},
splitLine: {
lineStyle: {
color: ['#eee']
}
}
},
valueAxis: {
axisLine: {
lineStyle: {
color: '#008acd'
}
},
splitArea : {
show : true,
areaStyle : {
color: ['rgba(250,250,250,0.1)','rgba(200,200,200,0.1)']
}
},
splitLine: {
lineStyle: {
color: ['#eee']
}
}
},
timeline : {
lineStyle : {
color : '#008acd'
},
controlStyle : {
normal : { color : '#008acd'},
emphasis : { color : '#008acd'}
},
symbol : 'emptyCircle',
symbolSize : 3
},
line: {
smooth : true,
symbol: 'emptyCircle',
symbolSize: 3
},
candlestick: {
itemStyle: {
normal: {
color: '#d87a80',
color0: '#2ec7c9',
lineStyle: {
color: '#d87a80',
color0: '#2ec7c9'
}
}
}
},
scatter: {
symbol: 'circle',
symbolSize: 4
},
map: {
label: {
normal: {
textStyle: {
color: '#d87a80'
}
}
},
itemStyle: {
normal: {
borderColor: '#eee',
areaColor: '#ddd'
},
emphasis: {
areaColor: '#fe994e'
}
}
},
graph: {
color: colorPalette
},
gauge : {
axisLine: {
lineStyle: {
color: [[0.2, '#2ec7c9'],[0.8, '#5ab1ef'],[1, '#d87a80']],
width: 10
}
},
axisTick: {
splitNumber: 10,
length :15,
lineStyle: {
color: 'auto'
}
},
splitLine: {
length :22,
lineStyle: {
color: 'auto'
}
},
pointer : {
width : 5
}
}
};
echarts.registerTheme('macarons', theme);
}));

View File

@@ -1,10 +1,10 @@
<template>
<transition :name="transitionName">
<div v-show="visible" :style="customStyle" class="back-to-ceiling" @click="backToTop">
<div class="back-to-ceiling" @click="backToTop" v-show="visible" :style="customStyle">
<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>
<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"></path>
</g>
</svg>
</div>
@@ -25,16 +25,14 @@ export default {
},
customStyle: {
type: Object,
default: function() {
return {
right: '50px',
bottom: '50px',
width: '40px',
height: '40px',
'border-radius': '4px',
'line-height': '45px',
background: '#e7eaf1'
}
default: {
right: '50px',
bottom: '50px',
width: '40px',
height: '40px',
'border-radius': '4px',
'line-height': '45px',
background: '#e7eaf1'
}
},
transitionName: {
@@ -45,8 +43,7 @@ export default {
data() {
return {
visible: false,
interval: null,
isMoving: false
interval: null
}
},
mounted() {
@@ -63,16 +60,13 @@ export default {
this.visible = window.pageYOffset > this.visibilityHeight
},
backToTop() {
if (this.isMoving) return
const start = window.pageYOffset
let i = 0
this.isMoving = true
this.interval = setInterval(() => {
const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
if (next <= this.backPosition) {
window.scrollTo(0, this.backPosition)
clearInterval(this.interval)
this.isMoving = false
} else {
window.scrollTo(0, next)
}
@@ -88,29 +82,29 @@ export default {
</script>
<style scoped>
.back-to-ceiling {
position: fixed;
display: inline-block;
text-align: center;
cursor: pointer;
}
.back-to-ceiling {
position: fixed;
display: inline-block;
text-align: center;
cursor: pointer;
}
.back-to-ceiling:hover {
background: #d5dbe7;
}
.back-to-ceiling:hover {
background: #d5dbe7;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity .5s;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity .5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0
}
.fade-enter,
.fade-leave-to {
opacity: 0
}
.back-to-ceiling .Icon {
fill: #9aaabf;
background: none;
}
.back-to-ceiling .Icon {
fill: #9aaabf;
background: none;
}
</style>

View File

@@ -1,20 +1,19 @@
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
<span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{
generateTitle(item.meta.title) }}</span>
<a v-else @click.prevent="handleLink(item)">{{ generateTitle(item.meta.title) }}</a>
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path" v-if='item.meta.title'>
<span v-if='item.redirect==="noredirect"||index==levelList.length-1' class="no-redirect">{{generateTitle(item.meta.title)}}</span>
<router-link v-else :to="item.redirect||item.path">{{generateTitle(item.meta.title)}}</router-link>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script>
import { generateTitle } from '@/utils/i18n'
import pathToRegexp from 'path-to-regexp'
export default {
created() {
this.getBreadcrumb()
},
data() {
return {
levelList: null
@@ -25,49 +24,31 @@ export default {
this.getBreadcrumb()
}
},
created() {
this.getBreadcrumb()
},
methods: {
generateTitle,
getBreadcrumb() {
let matched = this.$route.matched.filter(item => item.name)
const first = matched[0]
if (first && first.name.trim().toLocaleLowerCase() !== 'Dashboard'.toLocaleLowerCase()) {
if (first && first.name !== 'dashboard') {
matched = [{ path: '/dashboard', meta: { title: 'dashboard' }}].concat(matched)
}
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
this.levelList = matched
},
pathCompile(path) {
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
const { params } = this.$route
var toPath = pathToRegexp.compile(path)
return toPath(params)
},
handleLink(item) {
const { redirect, path } = item
if (redirect) {
this.$router.push(redirect)
return
}
this.$router.push(this.pathCompile(path))
generateTitle(title) {
return this.$t('route.' + title)
}
}
}
</script>
<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 50px;
margin-left: 8px;
.no-redirect {
color: #97a8be;
cursor: text;
<style rel="stylesheet/scss" lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 50px;
margin-left: 10px;
.no-redirect {
color: #97a8be;
cursor: text;
}
}
}
</style>

View File

@@ -1,13 +1,11 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :class="className" :id="id" :style="{height:height,width:width}"></div>
</template>
<script>
import echarts from 'echarts'
import resize from './mixins/resize'
export default {
mixins: [resize],
props: {
className: {
type: String,
@@ -56,10 +54,6 @@ export default {
this.chart.setOption(
{
backgroundColor: '#08263a',
grid: {
left: '5%',
right: '5%'
},
xAxis: [{
show: false,
data: xAxisData

View File

@@ -1,13 +1,11 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :class="className" :id="id" :style="{height:height,width:width}"></div>
</template>
<script>
import echarts from 'echarts'
import resize from './mixins/resize'
export default {
mixins: [resize],
props: {
className: {
type: String,
@@ -48,14 +46,13 @@ export default {
this.chart.setOption({
backgroundColor: '#394056',
title: {
top: 20,
text: 'Requests',
text: '请求数',
textStyle: {
fontWeight: 'normal',
fontSize: 16,
color: '#F1F1F3'
},
left: '1%'
left: '6%'
},
tooltip: {
trigger: 'axis',
@@ -66,12 +63,11 @@ export default {
}
},
legend: {
top: 20,
icon: 'rect',
itemWidth: 14,
itemHeight: 5,
itemGap: 13,
data: ['CMCC', 'CTCC', 'CUCC'],
data: ['移动', '电信', '联通'],
right: '4%',
textStyle: {
fontSize: 12,
@@ -79,10 +75,9 @@ export default {
}
},
grid: {
top: 100,
left: '2%',
right: '2%',
bottom: '2%',
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [{
@@ -97,7 +92,7 @@ export default {
}],
yAxis: [{
type: 'value',
name: '(%)',
name: '单位(%',
axisTick: {
show: false
},
@@ -119,7 +114,7 @@ export default {
}
}],
series: [{
name: 'CMCC',
name: '移动',
type: 'line',
smooth: true,
symbol: 'circle',
@@ -153,7 +148,7 @@ export default {
},
data: [220, 182, 191, 134, 150, 120, 110, 125, 145, 122, 165, 122]
}, {
name: 'CTCC',
name: '电信',
type: 'line',
smooth: true,
symbol: 'circle',
@@ -187,7 +182,7 @@ export default {
},
data: [120, 110, 125, 145, 122, 165, 122, 220, 182, 191, 134, 150]
}, {
name: 'CUCC',
name: '联通',
type: 'line',
smooth: true,
symbol: 'circle',

Some files were not shown because too many files have changed in this diff Show More