├── static
├── .gitkeep
└── assets
│ └── img
│ ├── logo.png
│ └── background-1.jpg
├── src
├── store
│ ├── getters.js
│ ├── actions.js
│ ├── index.js
│ ├── mutation-types.js
│ └── modules
│ │ ├── storage.js
│ │ ├── user.js
│ │ └── layout.js
├── assets
│ └── logo.png
├── views
│ ├── layout
│ │ ├── abstract.vue
│ │ ├── breadcrumb.vue
│ │ ├── tabs.vue
│ │ ├── ceiling.vue
│ │ ├── css
│ │ │ └── layout.css
│ │ └── sidebar.vue
│ ├── index.vue
│ ├── home
│ │ └── home.vue
│ ├── profile
│ │ └── profile.vue
│ ├── login.vue
│ ├── table
│ │ └── table.vue
│ └── user
│ │ ├── user-list.vue
│ │ └── new-user-list.vue
├── components
│ ├── form-type
│ │ ├── index.js
│ │ └── image.vue
│ ├── table
│ │ ├── expandRow.vue
│ │ ├── operation.vue
│ │ └── searchCriteria.vue
│ ├── info-card
│ │ └── infoCard.vue
│ ├── Hello.vue
│ ├── echarts
│ │ ├── pieChart.vue
│ │ ├── shadowChart.vue
│ │ ├── gaugeChart.vue
│ │ └── lineChart.vue
│ ├── edit-modal
│ │ ├── editModal.vue
│ │ └── editFormItem.vue
│ └── base
│ │ ├── baseView.vue
│ │ └── baseView.js
├── styles
│ ├── common.less
│ └── dark.theme.css
├── App.vue
├── api
│ ├── shop.js
│ └── user.api.js
├── libs
│ ├── qiniu.js
│ ├── util.js
│ └── httpUtil.js
├── main.js
├── plugins
│ └── logger.js
└── router
│ └── index.js
├── .eslintignore
├── gifs
└── iadmin.gif
├── config
├── prod.env.js
├── dev.env.js
└── index.js
├── docs
├── static
│ ├── assets
│ │ └── img
│ │ │ ├── logo.png
│ │ │ └── background-1.jpg
│ ├── fonts
│ │ ├── ionicons.05acfdb.woff
│ │ ├── ionicons.24712f6.ttf
│ │ └── ionicons.2c2ae06.eot
│ └── js
│ │ ├── manifest.d02a66532530d0778726.js
│ │ └── app.913abfd9f36004fe6b4f.js
└── index.html
├── .editorconfig
├── .gitignore
├── .postcssrc.js
├── index.html
├── .babelrc
├── README.md
├── .eslintrc.js
├── LICENSE
└── package.json
/static/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/store/getters.js:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | build/*.js
2 | config/*.js
3 |
--------------------------------------------------------------------------------
/gifs/iadmin.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyLuo/iview-vue-admin/HEAD/gifs/iadmin.gif
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyLuo/iview-vue-admin/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/static/assets/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyLuo/iview-vue-admin/HEAD/static/assets/img/logo.png
--------------------------------------------------------------------------------
/config/prod.env.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | NODE_ENV: '"production"',
3 | BASE_URL: '"http://localhost:8090"'
4 | }
5 |
--------------------------------------------------------------------------------
/docs/static/assets/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyLuo/iview-vue-admin/HEAD/docs/static/assets/img/logo.png
--------------------------------------------------------------------------------
/static/assets/img/background-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyLuo/iview-vue-admin/HEAD/static/assets/img/background-1.jpg
--------------------------------------------------------------------------------
/docs/static/assets/img/background-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyLuo/iview-vue-admin/HEAD/docs/static/assets/img/background-1.jpg
--------------------------------------------------------------------------------
/docs/static/fonts/ionicons.05acfdb.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyLuo/iview-vue-admin/HEAD/docs/static/fonts/ionicons.05acfdb.woff
--------------------------------------------------------------------------------
/docs/static/fonts/ionicons.24712f6.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyLuo/iview-vue-admin/HEAD/docs/static/fonts/ionicons.24712f6.ttf
--------------------------------------------------------------------------------
/docs/static/fonts/ionicons.2c2ae06.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyLuo/iview-vue-admin/HEAD/docs/static/fonts/ionicons.2c2ae06.eot
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/src/views/layout/abstract.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | *.suo
11 | *.ntvs*
12 | *.njsproj
13 | *.sln
14 |
--------------------------------------------------------------------------------
/config/dev.env.js:
--------------------------------------------------------------------------------
1 | var merge = require('webpack-merge')
2 | var prodEnv = require('./prod.env')
3 |
4 | module.exports = merge(prodEnv, {
5 | NODE_ENV: '"development"',
6 | BASE_URL: '"http://localhost:8090"'
7 | })
8 |
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | // to edit target browsers: use "browserslist" field in package.json
6 | "autoprefixer": {}
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/store/actions.js:
--------------------------------------------------------------------------------
1 | import * as types from './mutation-types'
2 |
3 | export const addToCart = ({commit}, product) => {
4 | if (product.inventory > 0) {
5 | commit(types.ADD_TO_CART, {
6 | id: product.id
7 | })
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | iview-vue-admin
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/components/form-type/index.js:
--------------------------------------------------------------------------------
1 | import ImageItem from './image.vue'
2 |
3 | const formType = {
4 | install: function (Vue) { //核心部分,在我们使用Vue.use()时,自动调用的是install,而install导出的必须是的组件
5 | Vue.component('imageItem', ImageItem);
6 | }
7 | };
8 | export default formType;
9 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-runtime"],
12 | "env": {
13 | "test": {
14 | "presets": ["env", "stage-2"],
15 | "plugins": ["istanbul"]
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/styles/common.less:
--------------------------------------------------------------------------------
1 | @import '~iview/src/styles/index.less';
2 |
3 | @font-size-base: 14px;
4 | @font-size-small: 14px;
5 | //@background-color-base: #fbfdff; // base
6 | //@table-td-stripe-bg: #fbfdff;
7 | .align-middle {
8 | position: relative;
9 | top: 50%;
10 | text-align: center;
11 | -webkit-transform: translateY(-50%);
12 | -ms-transform: translateY(-50%);
13 | transform: translateY(-50%);
14 | }
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
23 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | iview-vue-admin
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import * as actions from './actions'
4 | import * as getters from './getters'
5 | import createLogger from '../plugins/logger'
6 |
7 | import storage from './modules/storage'
8 | import layout from './modules/layout'
9 | import user from './modules/user'
10 |
11 | Vue.use(Vuex)
12 |
13 | const debug = process.env.NODE_ENV !== 'production'
14 | export default new Vuex.Store({
15 | actions,
16 | getters,
17 | modules: {
18 | storage,
19 | layout,
20 | user
21 | },
22 | strict: debug,
23 | plugins: debug ? [createLogger()] : []
24 | })
25 |
--------------------------------------------------------------------------------
/src/views/layout/breadcrumb.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 首页
5 |
6 |
10 | {{item.title}}
11 |
12 |
13 |
14 |
15 |
19 |
34 |
--------------------------------------------------------------------------------
/src/api/shop.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Mocking client-server processing
3 | */
4 | const _products = [
5 | {'id': 1, 'title': 'iPad 4 Mini', 'price': 500.01, 'inventory': 2},
6 | {'id': 2, 'title': 'H&M T-Shirt White', 'price': 10.99, 'inventory': 10},
7 | {'id': 3, 'title': 'Charli XCX - Sucker CD', 'price': 19.99, 'inventory': 5}
8 | ]
9 |
10 | export default {
11 | getProducts (cb) {
12 | setTimeout(() => cb(_products), 100)
13 | },
14 |
15 | buyProducts (products, cb, errorCb) {
16 | setTimeout(() => {
17 | // simulate random checkout failure.
18 | (Math.random() > 0.5 || navigator.userAgent.indexOf('PhantomJS') > -1)
19 | ? cb()
20 | : errorCb()
21 | }, 100)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/store/mutation-types.js:
--------------------------------------------------------------------------------
1 | export const ADD_TO_CART = 'ADD_TO_CART'
2 |
3 |
4 | //util
5 | export const SET_STORAGE = 'SET_STORAGE'
6 |
7 | // layout
8 | export const INIT_LAYOUT = 'INIT_LAYOUT'
9 | export const SET_LAYOUT_STATUS = 'SET_LAYOUT_STATUS'
10 | export const SET_MENU_LIST = 'SET_MENU_LIST'
11 | export const SET_TAB_LIST = 'SET_TAB_LIST'
12 | export const ADD_TAB = 'ADD_TAB'
13 | export const OPEN_TAB = 'OPEN_TAB'
14 | export const REMOVE_TAB = 'REMOVE_TAB'
15 | export const SET_OPENED_TAB_LIST = 'SET_OPENED_TAB_LIST'
16 | export const SET_CURRENT_PATH = 'SET_CURRENT_PATH'
17 | export const SET_OPENED_MENU_LIST = 'SET_OPENED_MENU_LIST'
18 |
19 | //user
20 | export const SET_USER = 'SET_USER'
21 | export const CLEAR_USER = 'CLEAR_USER'
22 | export const SET_USER_TOKEN = 'SET_USER_TOKEN'
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/store/modules/storage.js:
--------------------------------------------------------------------------------
1 | import * as types from '../mutation-types';
2 | const state = {
3 | storage: sessionStorage
4 | };
5 | // getters
6 | const getters = {
7 | storage : state => {
8 | return state.storage
9 | }
10 | }
11 | const actions = {
12 | changeStorage: function({commit}, rememberMe) {
13 | localStorage.setItem('rememberMe', rememberMe);
14 | // localStorage.removeItem("rememberMe"); //undefined
15 |
16 | commit(types.SET_STORAGE, rememberMe);
17 | }
18 | };
19 |
20 | const mutations = {
21 | [types.SET_STORAGE]: (state, rememberMe) => {
22 | if (rememberMe) {
23 | state.storage = localStorage;
24 | } else {
25 | state.storage = sessionStorage;
26 | }
27 | }
28 | };
29 | export default {
30 | state,
31 | getters,
32 | mutations,
33 | actions
34 | };
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # iview-vue-admin
2 |
3 | > iView Vue Admin
4 |
5 | ## Live Demo:
6 | - [https://tonyluo.github.io/iview-vue-admin](https://tonyluo.github.io/iview-vue-admin)
7 |
8 | 
9 |
10 |
11 |
12 | ## Build Setup
13 |
14 | ``` bash
15 | # install dependencies
16 | npm install
17 |
18 | # serve with hot reload at localhost:8080
19 | npm run dev
20 |
21 | # build for production with minification
22 | npm run build
23 |
24 | # build for production and view the bundle analyzer report
25 | npm run build --report
26 | ```
27 |
28 | ## Links
29 |
30 | - [Vue](https://github.com/vuejs/vue)
31 | - [Webpack](https://github.com/webpack/webpack)
32 | - [iView](https://github.com/iview/)
33 |
34 | ## License
35 | [MIT](http://opensource.org/licenses/MIT)
36 |
37 | This project is built base on iview@2.x, some code is from the iview official demo
38 |
39 | Copyright (c) 2017-present, Tony Luo
40 |
--------------------------------------------------------------------------------
/src/components/table/expandRow.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 | {{column.title}}:
12 |
17 |
18 | |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
41 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // http://eslint.org/docs/user-guide/configuring
2 | module.exports = {
3 | "root": true,
4 | extends: [
5 | // 'eslint:recommended',
6 | 'plugin:vue/recommended' // or 'plugin:vue/base'
7 | ],
8 | rules: {
9 | // override/add rules' settings here
10 | // 'vue/valid-v-if': 'error'
11 | }
12 | }
13 |
14 | //
15 | // module.exports = {
16 | // root: true,
17 | // parser: 'babel-eslint',
18 | // parserOptions: {
19 | // sourceType: 'module'
20 | // },
21 | // env: {
22 | // browser: true,
23 | // },
24 | // // https://github.com/standard/standard/blob/master/docs/RULES-en.md
25 | // extends: 'standard',
26 | // // required to lint *.vue files
27 | // plugins: [
28 | // 'html'
29 | // ],
30 | // // add your custom rules here
31 | // 'rules': {
32 | // // allow paren-less arrow functions
33 | // 'arrow-parens': 0,
34 | // // allow async-await
35 | // 'generator-star-spacing': 0,
36 | // // allow debugger during development
37 | // 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
38 | // }
39 | // }
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 TonyLuo
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/libs/qiniu.js:
--------------------------------------------------------------------------------
1 | import httpUtil from './httpUtil'
2 |
3 | export default
4 | {
5 | getToken () {
6 | return JSON.parse(localStorage.getItem('upload_token'))
7 | },
8 | hasValidToken () {
9 | const token = this.getToken();
10 | return token && token.expires_at && token.expires_at > new Date().getTime()
11 | },
12 | getUploadToken () {
13 | if (this.hasValidToken()) {
14 | return Promise.resolve(this.getToken())
15 | }
16 | return new Promise((resolve, reject) => {
17 | httpUtil.fetch({
18 | url: '/qiniu/get-upload-token',
19 | method: 'get'
20 | }).then(response => {
21 | const token = response.data.upload_token;
22 | const domainName = response.data.domain_name;
23 | let expiredAt = new Date();
24 | expiredAt.setSeconds(expiredAt.getSeconds() + response.data.expires_in);
25 | const uploadToken = {token: token, domain_name: domainName, expires_at: expiredAt.getTime()};
26 | localStorage.setItem('upload_token', JSON.stringify(uploadToken));
27 | resolve(uploadToken)
28 | }).catch(err => {
29 | reject(err)
30 | })
31 | })
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/components/info-card/infoCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
{{count}}
13 |
{{ message }}
14 |
15 |
16 |
17 |
18 |
19 |
46 |
61 |
--------------------------------------------------------------------------------
/docs/static/js/manifest.d02a66532530d0778726.js:
--------------------------------------------------------------------------------
1 | !function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,i){for(var u,a,f,s=0,l=[];s
2 | @import "../../styles/common.less";
3 |
4 | .operation-icon {
5 | color: @primary-color;
6 | padding: 5px;
7 | text-align: center;
8 | cursor: pointer;
9 | }
10 |
11 | .operation-icon:hover {
12 | color: @warning-color;
13 | }
14 |
15 |
16 |
17 |
18 |
19 |
22 |
26 |
27 |
32 |
33 |
34 |
35 |
36 |
60 |
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | // see http://vuejs-templates.github.io/webpack for documentation.
2 | var path = require('path')
3 |
4 | module.exports = {
5 | build: {
6 | env: require('./prod.env'),
7 | index: path.resolve(__dirname, '../dist/index.html'),
8 | assetsRoot: path.resolve(__dirname, '../dist'),
9 | assetsSubDirectory: 'static',
10 | assetsPublicPath: './',
11 | productionSourceMap: false,
12 | // Gzip off by default as many popular static hosts such as
13 | // Surge or Netlify already gzip all static assets for you.
14 | // Before setting to `true`, make sure to:
15 | // npm install --save-dev compression-webpack-plugin
16 | productionGzip: false,
17 | productionGzipExtensions: ['js', 'css'],
18 | // Run the build command with an extra argument to
19 | // View the bundle analyzer report after build finishes:
20 | // `npm run build --report`
21 | // Set to `true` or `false` to always turn it on or off
22 | bundleAnalyzerReport: process.env.npm_config_report
23 | },
24 | dev: {
25 | env: require('./dev.env'),
26 | port: 8080,
27 | autoOpenBrowser: true,
28 | assetsSubDirectory: 'static',
29 | assetsPublicPath: '/',
30 | proxyTable: {},
31 | // CSS Sourcemaps off by default because relative paths are "buggy"
32 | // with this option, according to the CSS-Loader README
33 | // (https://github.com/webpack/css-loader#sourcemaps)
34 | // In our experience, they generally work as expected,
35 | // just be aware of this issue when enabling this option.
36 | cssSourceMap: false
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/components/Hello.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
Essential Links
5 |
13 |
Ecosystem
14 |
20 |
21 |
22 |
23 |
33 |
34 |
35 |
54 |
--------------------------------------------------------------------------------
/src/api/user.api.js:
--------------------------------------------------------------------------------
1 | import httpUtil from '../libs/httpUtil'
2 |
3 | export default {
4 | url: '/users/',
5 | list (params) {
6 | let options = httpUtil.createQueryOption(params);
7 | return httpUtil.fetch({
8 | url: this.url + 'all' + options,
9 | method: 'get'
10 | });
11 | },
12 | fetchData (params) {
13 | let options = httpUtil.createQueryOption(params);
14 | return httpUtil.fetch({
15 | url: this.url + 'all' + options,
16 | method: 'get'
17 | });
18 | },
19 | create (data) {
20 | return httpUtil.fetch({
21 | url: `${this.url}/register`,
22 | method: 'post',
23 | data
24 | });
25 | },
26 | update (data) {
27 | return httpUtil.fetch({
28 | url: this.url,
29 | method: 'put',
30 | data
31 | });
32 | },
33 | find (id) {
34 | return httpUtil.fetch({
35 | url: this.url + encodeURIComponent(id),
36 | method: 'get'
37 | });
38 | },
39 | delete (id) {
40 | return httpUtil.fetch({
41 | url: `${this.url}/delete/${id}`,
42 | method: 'delete'
43 | });
44 | },
45 | advancedSearch(searchStr, params) {
46 | let options = httpUtil.createQueryOption(params);
47 | return httpUtil.fetch({
48 | url: this.url + 'adv/' + encodeURIComponent(searchStr) + options,
49 | method: 'get'
50 | });
51 | },
52 | login (data) {
53 | return httpUtil.fetch({
54 | url: '/authenticate',
55 | method: 'post',
56 | data
57 | })
58 | },
59 | getUserInfo(){
60 | return httpUtil.fetch({
61 | url: '/account',
62 | method: 'get'
63 | })
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/views/layout/tabs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
12 |
13 |
14 |
21 |
70 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | // The Vue build version to load with the `import` command
2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 | import Vue from 'vue'
4 | import VueRouter from 'vue-router'
5 | import Vuex from 'vuex'
6 |
7 | import iView from 'iview'
8 | import 'iview/dist/styles/iview.css'
9 | import App from './App'
10 | import store from './store'
11 | // import util from './libs/util'
12 | import {checkPermission} from './libs/util'
13 |
14 | import {routers} from './router'
15 |
16 | import formType from './components/form-type'
17 |
18 | Vue.use(VueRouter)
19 | Vue.use(Vuex)
20 | Vue.use(iView)
21 | Vue.use(formType)
22 |
23 | Vue.config.productionTip = false
24 |
25 |
26 | function guardRoute(route, redirect, next) {
27 | if (store.getters.token) {
28 | next()
29 | } else {
30 | next({path: '/login', query: {redirect: redirect.fullPath}});
31 | }
32 | // if(checkPermission(route)){
33 | // next()
34 | // }else{
35 | // redirect('/login')
36 | // }
37 | // if (window.confirm(`Navigate to ${route.path}?`)) {
38 | // next()
39 | // } else if (window.confirm(`Redirect to /baz?`)) {
40 | // redirect('/baz')
41 | // }
42 | }
43 |
44 | // 路由配置
45 | const RouterConfig = {
46 | mode: 'hash',
47 | routes: routers
48 | }
49 | const router = new VueRouter(RouterConfig)
50 |
51 | router.beforeEach((route, redirect, next) => {
52 | iView.LoadingBar.start()
53 | // util.title(route.meta.title)
54 |
55 | if (route.matched.some(m => m.meta.auth)) {
56 | guardRoute(route, redirect, next)
57 | } else {
58 | next()
59 | }
60 | })
61 |
62 | router.afterEach((to, from, next) => {
63 | iView.LoadingBar.finish()
64 | window.scrollTo(0, 0)
65 | })
66 |
67 | /* eslint-disable no-new */
68 | new Vue({
69 | el: '#app',
70 | store,
71 | router,
72 | template: '',
73 | components: {App}
74 | })
75 |
--------------------------------------------------------------------------------
/src/components/echarts/pieChart.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
68 |
--------------------------------------------------------------------------------
/src/plugins/logger.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-vars */
2 | // Credits: borrowed code from fcomb/redux-logger
3 |
4 | import { deepCopy } from '../libs/util'
5 |
6 | export default function createLogger ({
7 | collapsed = true,
8 | filter = (mutation, stateBefore, stateAfter) => true,
9 | transformer = state => state,
10 | mutationTransformer = mut => mut
11 | } = {}) {
12 | return store => {
13 | let prevState = deepCopy(store.state)
14 |
15 | store.subscribe((mutation, state) => {
16 | if (typeof console === 'undefined') {
17 | return
18 | }
19 | const nextState = deepCopy(state)
20 |
21 | if (filter(mutation, prevState, nextState)) {
22 | const time = new Date()
23 | const formattedTime = ` @ ${pad(time.getHours(), 2)}:${pad(time.getMinutes(), 2)}:${pad(time.getSeconds(), 2)}.${pad(time.getMilliseconds(), 3)}`
24 | const formattedMutation = mutationTransformer(mutation)
25 | const message = `mutation ${mutation.type}${formattedTime}`
26 | const startMessage = collapsed
27 | ? console.groupCollapsed
28 | : console.group
29 |
30 | // render
31 | try {
32 | startMessage.call(console, message)
33 | } catch (e) {
34 | console.log(message)
35 | }
36 |
37 | console.log('%c prev state', 'color: #9E9E9E; font-weight: bold', transformer(prevState))
38 | console.log('%c mutation', 'color: #03A9F4; font-weight: bold', formattedMutation)
39 | console.log('%c next state', 'color: #4CAF50; font-weight: bold', transformer(nextState))
40 |
41 | try {
42 | console.groupEnd()
43 | } catch (e) {
44 | console.log('—— log end ——')
45 | }
46 | }
47 |
48 | prevState = nextState
49 | })
50 | }
51 | }
52 |
53 | function repeat (str, times) {
54 | return (new Array(times + 1)).join(str)
55 | }
56 |
57 | function pad (num, maxLength) {
58 | return repeat('0', maxLength - num.toString().length) + num
59 | }
60 |
--------------------------------------------------------------------------------
/src/views/layout/ceiling.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 | 个人设置
10 | 退出登录
11 |
12 |
13 |
14 |
15 |
注册登录
16 |
帮助中心
17 |
安全中心
18 |
服务大厅
19 |
20 |
21 |
22 |
23 |
24 |
25 |
58 |
80 |
--------------------------------------------------------------------------------
/src/views/layout/css/layout.css:
--------------------------------------------------------------------------------
1 | /* Generic layout rules
2 | */
3 | body {
4 | margin: 0;
5 | -webkit-text-size-adjust: 100%;
6 | }
7 |
8 | .page {
9 | left: 0;
10 | right: 0;
11 | top: 0;
12 | bottom: 0;
13 | }
14 |
15 | .row, .col, .page {
16 | overflow: hidden;
17 | position: absolute;
18 | }
19 |
20 | .row {
21 | left: 0;
22 | right: 0;
23 | }
24 |
25 | .col {
26 | top: 0;
27 | bottom: 0;
28 | }
29 | .left.col {
30 | width: 200px;
31 | }
32 |
33 | .right.col {
34 | left: 200px;
35 | right: 0;
36 | }
37 |
38 | .header.row {
39 | height: 40px;
40 | line-height: 40px;
41 | }
42 | .header {
43 | font-size: 1.4em;
44 | }
45 |
46 | .body.row {
47 | top: 75px;
48 | bottom: 0;
49 | }
50 |
51 | /*.footer.row {*/
52 | /*height: 40px;*/
53 | /*bottom: 0;*/
54 | /*line-height: 40px;*/
55 | /*!*opacity:0.7;*!*/
56 | /*!*filter:Alpha(opacity=70); !* IE8 以及更早的浏览器 *!*!*/
57 | /*}*/
58 | .floating-right {
59 | float: right;
60 | transform: rotate(90deg);
61 | }
62 |
63 | .text-alight-left {
64 | text-align: left;
65 | }
66 |
67 | .text-alight-center {
68 | float: none;
69 | text-align: center;
70 | }
71 |
72 | .layout-tabs {
73 | float: left;
74 | padding: 5px 5px 0px 1em;
75 | }
76 |
77 | .layout-breadcrumb {
78 | float: right;
79 | padding: 5px 15px 0;
80 | }
81 |
82 | .scroll-x {
83 | overflow-x: auto;
84 | -webkit-overflow-scrolling: touch;
85 | }
86 |
87 | .scroll-y {
88 | overflow-y: auto;
89 | -webkit-overflow-scrolling: touch;
90 | }
91 |
92 | .fill, .pane {
93 | position: absolute;
94 | left: 0;
95 | top: 0;
96 | right: 0;
97 | bottom: 0;
98 | width: 100%;
99 | height: 100%
100 | }
101 |
102 | .pane {
103 | display: none;
104 | }
105 |
106 | /* Workaround: in landscape mode, IEMobile makes bottom toolbar overlap the page, so shorten the page by 75px to compensate */
107 | .iemobile .page {
108 | bottom: -6px;
109 | }
110 |
111 | @media screen and (orientation: landscape) {
112 | .iemobile .page {
113 | bottom: 75px;
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/components/echarts/shadowChart.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
71 |
--------------------------------------------------------------------------------
/src/views/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
40 |
41 |
74 |
--------------------------------------------------------------------------------
/src/styles/dark.theme.css:
--------------------------------------------------------------------------------
1 | /*
2 | refer to http://stevesanderson.github.io/fixed-height-layouts-demo/two-columns.html
3 | */
4 |
5 | body {
6 | font-family: 'Helvetica Neue', Arial, Sans-Serif;
7 | }
8 |
9 | .header, .footer {
10 | color: #eee;
11 | background: #464c5b;
12 | text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
13 | padding: 0 0.5em;
14 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #696f77), color-stop(100%, #28343b));
15 | background: -webkit-linear-gradient(top, #696f77 0%, #28343b 100%);
16 | background: -ms-linear-gradient(top, #696f77 0%, #28343b 100%);
17 | }
18 |
19 |
20 |
21 | .body, .pane {
22 | background: #ddd
23 | }
24 |
25 | /*.right.col { border-left: 1px solid black; }*/
26 | .right.col .body {
27 | padding: 0 1em;
28 | background: #fff
29 | }
30 |
31 | .left.col .body {
32 | background: #495060;
33 | }
34 |
35 | .listview {
36 | padding: 0;
37 | margin: 0;
38 | font-weight: bold;
39 | color: #444;
40 | }
41 |
42 | .listview li {
43 | list-style-type: none;
44 | background: #eee;
45 | padding: 1em;
46 | border-top: 1px solid #aaa;
47 | border-bottom: 1px solid #fff;
48 | cursor: pointer;
49 | }
50 |
51 | .listview li.selected {
52 | background-color: #37F;
53 | color: White;
54 | }
55 |
56 | .listview.inset {
57 | margin: 1em 0;
58 | }
59 |
60 | .listview.inset li {
61 | background: white;
62 | border: 2px solid #aaa;
63 | border-bottom-width: 0;
64 | }
65 |
66 | .listview.inset li:first-child {
67 | border-radius: 1em 1em 0em 0em
68 | }
69 |
70 | .listview.inset li:last-child {
71 | border-radius: 0em 0em 1em 1em;
72 | border-bottom-width: 2px;
73 | }
74 |
75 | .tiles {
76 | overflow-y: hidden;
77 | }
78 |
79 | .tiles > ul {
80 | width: 1175px;
81 | }
82 |
83 | .tiles ul {
84 | margin: 0;
85 | padding: 0;
86 | white-space: nowrap;
87 | }
88 |
89 | .tiles li {
90 | list-style-type: none;
91 | display: inline-block;
92 | background-color: #080;
93 | width: 150px;
94 | height: 150px;
95 | padding: 1em;
96 | color: White;
97 | margin: 5px;
98 | font-weight: bold;
99 | zoom: 1;
100 | *display: inline;
101 | }
102 |
103 | button {
104 | display: block;
105 | border: 2px solid #aaa;
106 | line-height: normal;
107 | background-color: White;
108 | border-radius: 8px;
109 | margin: 8px 0;
110 | cursor: pointer;
111 | padding: 5px 20px;
112 | font-weight: bold;
113 | color: #333;
114 | }
115 |
--------------------------------------------------------------------------------
/src/components/edit-modal/editModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
99 |
--------------------------------------------------------------------------------
/src/components/echarts/gaugeChart.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
97 |
--------------------------------------------------------------------------------
/src/components/edit-modal/editFormItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 | {{item.meta.option.openText}}
9 | {{item.meta.option.closeText}}
10 |
11 |
12 | {{opt.label}}
15 |
16 |
17 |
21 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
89 |
--------------------------------------------------------------------------------
/src/components/base/baseView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
21 |
22 |
23 |
24 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | 删除确认
60 |
61 |
62 |
删除后将无法恢复
63 |
是否继续删除?
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "iview-vue-admin",
3 | "version": "1.0.0",
4 | "description": "Vue Admin Template bases on iView",
5 | "author": "Tony ",
6 | "private": true,
7 | "scripts": {
8 | "dev": "node build/dev-server.js",
9 | "start": "node build/dev-server.js",
10 | "build": "node build/build.js",
11 | "lint": "eslint --ext .js,.vue src"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git@github.com:TonyLuo/iview-vue-admin.git"
16 | },
17 | "homepage": "https://github.com/TonyLuo/iview-vue-admin",
18 | "keywords": [
19 | "vue",
20 | "iview",
21 | "element",
22 | "ui",
23 | "admin",
24 | "vue admin",
25 | "管理",
26 | "后台",
27 | "管理后台",
28 | "后台模板"
29 | ],
30 | "license": "MIT",
31 | "dependencies": {
32 | "axios": "^0.16.2",
33 | "echarts": "^3.7.2",
34 | "iview": "^2.4.0",
35 | "vue": "^2.4.4",
36 | "vue-router": "^2.7.0",
37 | "vuex": "^2.4.1"
38 | },
39 | "devDependencies": {
40 | "autoprefixer": "^7.1.2",
41 | "babel-core": "^6.22.1",
42 | "babel-eslint": "^7.1.1",
43 | "babel-loader": "^7.1.1",
44 | "babel-plugin-transform-runtime": "^6.22.0",
45 | "babel-preset-env": "^1.3.2",
46 | "babel-preset-es2015": "^6.24.1",
47 | "babel-preset-stage-2": "^6.22.0",
48 | "babel-register": "^6.22.0",
49 | "babel-webpack-plugin": "^0.1.1",
50 | "chalk": "^2.0.1",
51 | "connect-history-api-fallback": "^1.3.0",
52 | "copy-webpack-plugin": "^4.0.1",
53 | "css-loader": "^0.28.0",
54 | "cssnano": "^3.10.0",
55 | "eslint": "^3.19.0",
56 | "eslint-config-standard": "^6.2.1",
57 | "eslint-friendly-formatter": "^3.0.0",
58 | "eslint-loader": "^1.7.1",
59 | "eslint-plugin-html": "^3.0.0",
60 | "eslint-plugin-promise": "^3.4.0",
61 | "eslint-plugin-standard": "^2.0.1",
62 | "eslint-plugin-vue": "^3.13.0",
63 | "eslint-plugin-vuefix": "^0.2.1",
64 | "eventsource-polyfill": "^0.9.6",
65 | "express": "^4.14.1",
66 | "extract-text-webpack-plugin": "^2.0.0",
67 | "file-loader": "^0.11.1",
68 | "friendly-errors-webpack-plugin": "^1.1.3",
69 | "html-webpack-plugin": "^2.28.0",
70 | "http-proxy-middleware": "^0.17.3",
71 | "iview-loader": "^1.0.0-beta.4",
72 | "less": "^2.7.2",
73 | "less-loader": "^4.0.5",
74 | "opn": "^5.1.0",
75 | "optimize-css-assets-webpack-plugin": "^2.0.0",
76 | "ora": "^1.2.0",
77 | "rimraf": "^2.6.0",
78 | "semver": "^5.3.0",
79 | "shelljs": "^0.7.6",
80 | "url-loader": "^0.5.8",
81 | "vue-loader": "^13.0.4",
82 | "vue-style-loader": "^3.0.1",
83 | "vue-template-compiler": "^2.4.2",
84 | "webpack": "^2.6.1",
85 | "webpack-bundle-analyzer": "^2.2.1",
86 | "webpack-dev-middleware": "^1.10.0",
87 | "webpack-hot-middleware": "^2.18.0",
88 | "webpack-merge": "^4.1.0"
89 | },
90 | "engines": {
91 | "node": ">= 4.0.0",
92 | "npm": ">= 3.0.0"
93 | },
94 | "browserslist": [
95 | "> 1%",
96 | "last 2 versions",
97 | "not ie <= 8"
98 | ]
99 | }
100 |
--------------------------------------------------------------------------------
/src/views/home/home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
17 |
18 |
19 |
24 |
25 |
26 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | 广告投放分析
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | 各类用户服务调用变化统计
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | 用户访问来源
66 |
67 |
68 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | 上周每日服务调用量
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
108 |
109 |
114 |
--------------------------------------------------------------------------------
/src/components/echarts/lineChart.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
113 |
--------------------------------------------------------------------------------
/src/store/modules/user.js:
--------------------------------------------------------------------------------
1 | import * as types from '../mutation-types'
2 | import storage from './storage'
3 | import user from '../../api/user.api'
4 |
5 | const state = {
6 | userDetail: {},
7 | token: {},
8 | userId: null
9 | }
10 | // getters
11 | const getters = {
12 | token: state => {
13 | // check whether the token still valid
14 | let strToken = storage.state.storage.getItem('userToken')
15 | let localToken = null
16 | if (strToken) {
17 | localToken = JSON.parse(strToken)
18 | }
19 | let token = localToken || state.token
20 | if (token.expiresTime) {
21 | if (token.expiresTime > new Date().getTime()) {
22 | return token.userToken
23 | } else {
24 | return null
25 | }
26 | }
27 | },
28 | userDetail: state => {
29 | return state.userDetail
30 | },
31 | roles: state => {
32 | return state.userDetail.authorities
33 | }
34 | }
35 |
36 | const mutations = {
37 |
38 | [types.SET_USER]: (state, user) => {
39 | if (user) {
40 | state.userDetail = user
41 | state.userId = user.id
42 | storage.state.storage.setItem('userId', user.id)
43 | }
44 | },
45 | [types.SET_USER_TOKEN]: (state, token) => {
46 | if (token && token.userToken) {
47 | state.token = token
48 | }
49 |
50 | },
51 | [types.CLEAR_USER]: (state) => {
52 | state.userDetail = {}
53 | state.userId = null
54 | localStorage.clear()
55 | sessionStorage.clear()
56 | }
57 | }
58 | const actions = {
59 | initApp({dispatch, commit}, data) {
60 | dispatch('initUser')
61 |
62 | },
63 | initUser({dispatch, commit}, data) {
64 | dispatch('initUserToken', data).then(() => {
65 | dispatch('setUser')
66 | })
67 | },
68 | setUser({dispatch, commit, state}) {
69 | if (state.token.userToken) {
70 | user.getUserInfo().then(res => {
71 | commit(types.SET_USER, res.data)
72 |
73 | })
74 | }
75 |
76 | },
77 | initUserToken({dispatch, commit}, token) {
78 | // get token through backend api
79 | if (token && token.id_token) {
80 |
81 | let now = new Date()
82 | var nowTime = now.getTime()//转化为时间戳毫秒数
83 | let expiresTime = now.setTime(nowTime + 1000 * token.expires_in - 1000 * 60 * 10)//set expires time 10 minutes advanced 设置比真实失效时间提前十分钟
84 | let userToken = {userToken: token.id_token, expiresTime: expiresTime} //转成失效时间
85 | let strToken = JSON.stringify(userToken) //转化为JSON字符串
86 | storage.state.storage.setItem('userToken', strToken)
87 |
88 | commit(types.SET_USER_TOKEN, userToken)
89 | }
90 | else {
91 | // get token from localStorage/sessionStorage
92 | let strToken = storage.state.storage.getItem('userToken')
93 | if (strToken) {
94 | let localToken = JSON.parse(strToken)
95 | if (localToken.expiresTime > new Date().getTime()) {
96 | commit(types.SET_USER_TOKEN, localToken)
97 |
98 | } else {
99 | commit(types.CLEAR_USER)
100 | }
101 | }
102 |
103 | }
104 | },
105 |
106 | logout({dispatch, commit}) {
107 | commit(types.CLEAR_USER)
108 |
109 | }
110 |
111 | }
112 |
113 | export default {
114 | state,
115 | getters,
116 | mutations,
117 | actions
118 | }
119 |
--------------------------------------------------------------------------------
/src/libs/util.js:
--------------------------------------------------------------------------------
1 | import store from '../store'
2 |
3 | /**
4 | * Get the first item that pass the test
5 | * by second argument function
6 | *
7 | * @param {Array} list
8 | * @param {Function} f
9 | * @return {*}
10 | */
11 | function find (list, f) {
12 | return list.filter(f)[0]
13 | }
14 |
15 | /**
16 | * Deep copy the given object considering circular structure.
17 | * This function caches all nested objects and its copies.
18 | * If it detects circular structure, use cached copy to avoid infinite loop.
19 | *
20 | * @param {*} obj
21 | * @param {Array