├── .babelrc
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── README.md
├── build
├── dev-server.js
├── webpack.config.js
└── webpack.dist.config.js
├── index.html
├── package.json
├── postcss.config.js
└── src
├── components
├── common.scss
├── layout.vue
├── layout1.vue
└── modal.js
├── main.js
├── pages
├── item1
│ └── item1.vue
├── item2
│ └── item2.vue
└── item3
│ ├── echarts
│ └── line.vue
│ ├── option1.vue
│ └── option2.vue
├── store
├── index.js
└── modules
│ └── menu.js
├── testdata
└── localdata
│ ├── linelist.json
│ └── menulist.json
└── utils
├── axios.js
├── errorcode.js
└── localdata.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [["env", {
3 | "targets": {
4 | "browsers": ["last 2 versions"]
5 | }
6 | }]],
7 | "plugins": [
8 | ["transform-object-rest-spread"]
9 | ]
10 | }
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labnize/vue-vuex-router-element-webpack/665984fab646906002404f6fba82f724c01e79b6/.eslintignore
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // parser: 'babel-eslint',
3 | env: {
4 | browser: true,
5 | commonjs: true,
6 | es6: true
7 | },
8 | // extends: ['airbnb-base'],
9 | extends: ['plugin:vue/recommended', 'airbnb-base'],
10 | plugins: [
11 | 'vue'
12 | ],
13 | rules: {
14 | quotes: [2, 'single'],
15 | semi: 2,
16 | 'max-len': [1, 120, 2],
17 | 'arrow-body-style': [1, 'as-needed'],
18 | 'comma-dangle': [2, 'never'],
19 | 'no-debugger': 2,
20 | 'no-console': 2,
21 | 'object-curly-spacing': [2, 'always'],
22 | 'no-undef': [1],
23 | 'new-cap': 1,
24 | 'no-param-reassign': 0,
25 | 'global-require': 0,
26 | 'no-mixed-operators': 0,
27 | "import/no-extraneous-dependencies": 0,
28 | "import/no-unresolved": 0,
29 | "import/extensions": 0,
30 | "import/no-dynamic-require": 0,
31 | "import/no-duplicates": 0,
32 | "vue/max-attributes-per-line": 0
33 | }
34 | };
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | node_modules/
3 | dist/
4 |
5 | .DS_Store
6 | *.log
7 | *.log.*
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vue基础MVVM框架
2 |
3 | ## 技术及框架
4 |
5 | 包括但不限于:
6 |
7 | - ES6/7 JS
8 | - ESLint (代码规范)
9 | - Vue (MVVM框架)
10 | - Vuex (统一状态管理)
11 | - Vue Router (路由)
12 | - axios (http库)
13 | - Element UI (UI框架)
14 | - Babel (ES6/7代码转译浏览器可执行)
15 | - Webpack (打包工具)
16 |
17 | ## 安装调试
18 |
19 | ```bash
20 | npm i
21 | # 或 yarn
22 | npm run start
23 | # 或 yarn start
24 | ```
25 | ## 打包
26 |
27 | ```bash
28 | npm run build
29 | # or
30 | yarn build
31 | ```
32 |
--------------------------------------------------------------------------------
/build/dev-server.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const WebpackDevServer = require('webpack-dev-server');
3 | const webpackDevConfig = require('./webpack.config.js');
4 | const open = require('open');
5 |
6 | const compiler = webpack(webpackDevConfig);
7 | new WebpackDevServer(compiler, {
8 | contentBase: './',
9 | historyApiFallback: true,
10 | hot: true,
11 | noInfo: false,
12 | publicPath: '/',
13 | stats: { colors: true }
14 | }).listen(3001, 'localhost', () => {
15 | console.log('http://127.0.0.1:3001');
16 | console.log('Opening your system browser...');
17 | open('http://127.0.0.1:3001');
18 | });
19 |
20 |
--------------------------------------------------------------------------------
/build/webpack.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const path = require('path');
3 | const HtmlWebpackPlugin = require('html-webpack-plugin');
4 | const { VueLoaderPlugin } = require('vue-loader');
5 |
6 | const webpackConfig = {
7 | entry: {
8 | app: path.resolve(__dirname, '../src/main.js')
9 | },
10 | output: {
11 | filename: '[name].js',
12 | publicPath: '/'
13 | },
14 | cache: true,
15 | devtool: 'inline-source-map',
16 | resolve: {
17 | extensions: ['.js', '.vue'],
18 | alias: {
19 | vue$: 'vue/dist/vue.esm.js',
20 | components: path.join(__dirname, '../src/components'),
21 | pages: path.join(__dirname, '../src/pages'),
22 | localData: path.join(__dirname, '../src/testdata/localdata'),
23 | util: path.join(__dirname, '../src/utils')
24 | // jquery: path.join(__dirname, '../node_modules/jquery/dist/jquery.min.js')
25 | }
26 | },
27 | module: {
28 | rules: [
29 | {
30 | test: /\.vue$/,
31 | loader: 'vue-loader',
32 | options: {
33 | loaders: {
34 | scss: 'vue-style-loader!css-loader!sass-loader', //
135 |
--------------------------------------------------------------------------------
/src/components/layout1.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | July Design ©2017 Created by July
50 |
51 |
52 |
53 |
54 |
55 |
56 |
100 |
101 |
128 |
--------------------------------------------------------------------------------
/src/components/modal.js:
--------------------------------------------------------------------------------
1 | import { MessageBox, Message } from 'element-ui';
2 | import 'components/common.scss';
3 |
4 | const Modal = {
5 | confirmModal(data, ok) {
6 | MessageBox.confirm(data, {
7 | confirmButtonText: '确定',
8 | customClass: 'confirm-dialog',
9 | center: true,
10 | type: 'warning',
11 | showCancelButton: false
12 | }).then(() => {
13 | // ok确认回调可放到调用的地方,单独定义
14 | Message({
15 | type: 'success',
16 | message: '全部开启成功!'
17 | });
18 | }).catch(() => {
19 | Message({
20 | type: 'info',
21 | message: '已取消开启操作'
22 | });
23 | });
24 | }
25 | };
26 |
27 | export default Modal;
28 |
29 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import ElementUI from 'element-ui';
2 | import 'normalize.css';
3 | import 'element-ui/lib/theme-chalk/index.css';
4 | import Vue from 'vue';
5 | import VueRouter from 'vue-router';
6 |
7 | import item1 from 'pages/item1/item1';
8 | import item2 from 'pages/item2/item2';
9 | import item31 from 'pages/item3/option1';
10 | import item32 from 'pages/item3/option2';
11 |
12 | import store from './store';
13 |
14 | Vue.use(ElementUI);
15 | Vue.use(VueRouter);
16 | /* eslint-disable no-new */
17 |
18 | const router = new VueRouter({
19 | mode: 'history',
20 | base: __dirname,
21 | routes: [
22 | { path: '/', component: item1 },
23 | { path: '/item1', component: item1 },
24 | { path: '/item2', component: item2 },
25 | { path: '/item3-1', component: item31 },
26 | { path: '/item3-2', component: item32 }
27 | ]
28 | });
29 | new Vue({
30 | el: '#app',
31 | router,
32 | store,
33 | template: `
34 |
35 |
36 |
37 | `
38 | });
39 |
--------------------------------------------------------------------------------
/src/pages/item1/item1.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
15 |
30 |
31 |
34 |
--------------------------------------------------------------------------------
/src/pages/item2/item2.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
11 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
53 |
--------------------------------------------------------------------------------
/src/pages/item3/echarts/line.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
121 |
--------------------------------------------------------------------------------
/src/pages/item3/option1.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | 配置管理
11 | 角色管理
12 | 定时任务补偿
13 |
14 |
15 |
16 |
17 |
18 |
58 |
59 |
65 |
--------------------------------------------------------------------------------
/src/pages/item3/option2.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | option2
5 |
6 |
7 |
8 |
9 |
21 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuex from 'vuex';
3 | import menu from './modules/menu';
4 |
5 | Vue.use(Vuex);
6 |
7 | const store = new Vuex.Store({
8 | modules: {
9 | menu
10 | }
11 | });
12 |
13 | export default store;
14 |
--------------------------------------------------------------------------------
/src/store/modules/menu.js:
--------------------------------------------------------------------------------
1 | import Axios from 'util/axios';
2 |
3 | const menu = {
4 | state: {
5 | menuList: []
6 | },
7 | mutations: {
8 | CHANGE_MENULIST: (state, list) => {
9 | state.menuList = list;
10 | }
11 | },
12 | actions: {
13 | fetch({ commit }, param) {
14 | const params = {
15 | ...param,
16 | successFn(data) {
17 | if (data.list && data.list.length) {
18 | commit('CHANGE_MENULIST', data.list);
19 | }
20 | }
21 | };
22 | console.log(params);
23 | Axios.fetch(params);
24 | }
25 | }
26 | };
27 |
28 | export default menu;
29 |
--------------------------------------------------------------------------------
/src/testdata/localdata/linelist.json:
--------------------------------------------------------------------------------
1 | {
2 | "result": 0,
3 | "list": [
4 | {
5 | "id": "1",
6 | "name": "平台",
7 | "counttime": "2016-11-08 16:19",
8 | "successrate": 22,
9 | "maxsuccessimagerate": 82,
10 | "maxsuccessregionrate": 56,
11 | "maxfailimagerate": 92,
12 | "maxfailregionrate": 33
13 | },{
14 | "id": "2",
15 | "name": "平台",
16 | "counttime": "2016-11-08 17:19",
17 | "successrate": 32,
18 | "maxsuccessimagerate": 52,
19 | "maxsuccessregionrate": 66,
20 | "maxfailimagerate": 22,
21 | "maxfailregionrate": 23
22 | },{
23 | "id": "3",
24 | "name": "平台",
25 | "counttime": "2016-11-08 18:19",
26 | "successrate": 42,
27 | "maxsuccessimagerate": 32,
28 | "maxsuccessregionrate": 76,
29 | "maxfailimagerate": 32,
30 | "maxfailregionrate": 43
31 | },{
32 | "id": "4",
33 | "name": "平台",
34 | "counttime": "2016-11-08 19:19",
35 | "successrate": 22,
36 | "maxsuccessimagerate": 42,
37 | "maxsuccessregionrate": 6,
38 | "maxfailimagerate": 142,
39 | "maxfailregionrate": 13
40 | },{
41 | "id": "5",
42 | "name": "平台",
43 | "counttime": "2016-11-08 20:19",
44 | "successrate": 62,
45 | "maxsuccessimagerate": 52,
46 | "maxsuccessregionrate": 96,
47 | "maxfailimagerate": 52,
48 | "maxfailregionrate": 73
49 | }
50 | ],
51 | "message": "error"
52 | }
--------------------------------------------------------------------------------
/src/testdata/localdata/menulist.json:
--------------------------------------------------------------------------------
1 | {
2 | "result": 0,
3 | "list": [
4 | {
5 | "key": "item1",
6 | "name": "导航一"
7 | },
8 | {
9 | "key": "item2",
10 | "name": "导航二"
11 | },
12 | {
13 | "key": "item3",
14 | "name": "导航三",
15 | "sub": [
16 | {
17 | "key": "item3-1",
18 | "name": "选项1"
19 | }, {
20 | "key": "item3-2",
21 | "name": "选项2"
22 | }
23 | ]
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/src/utils/axios.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import { Loading } from 'element-ui';
3 | import { MessageBox } from 'element-ui';
4 | import 'components/common.scss';
5 | import ErrorCode from './errorcode';
6 |
7 | const localDatas = require('util/localdata');
8 |
9 | export default class AXIOS {
10 | constructor() {
11 | this.loading = '';
12 | }
13 |
14 | static getEnvPrefix() {
15 | if (window.isDebug) {
16 | return '';
17 | }
18 | return window.apiUrl;
19 | }
20 |
21 | static fetch(fetchObj) {
22 | const {
23 | loadingFlag,
24 | method,
25 | successFn,
26 | errorFn
27 | } = fetchObj;
28 | let {
29 | url,
30 | data = {}
31 | } = fetchObj;
32 |
33 | if (loadingFlag) {
34 | this.loading = Loading.service({
35 | lock: true,
36 | text: '加载中...',
37 | spinner: 'el-icon-loading',
38 | customClass: 'axios-loading',
39 | background: 'rgba(0, 0, 0, 0.7)'
40 | });
41 | }
42 | if (window.isDebug) {
43 | setTimeout(() => {
44 | if (loadingFlag) {
45 | this.loading.close();
46 | }
47 | const localData = localDatas[url];
48 | if (localData.result === 0) {
49 | successFn(localData);
50 | } else {
51 | const errorMsg = ErrorCode(localData.code) || '服务器异常,请联系运维人员!';
52 | if (errorFn) {
53 | errorFn(errorMsg);
54 | } else {
55 | AXIOS.modalError(errorMsg);
56 | }
57 | }
58 | }, 500);
59 | return;
60 | }
61 |
62 | url = this.getEnvPrefix() + url;
63 | if (method.toLowerCase() === 'get') {
64 | data = null;
65 | } else {
66 | data = JSON.stringify(data);
67 | }
68 |
69 | axios({
70 | method,
71 | url,
72 | data: {
73 | req: AXIOS.isExisty(data) ? data : {}
74 | },
75 | responseType: 'json'
76 | })
77 | .then((res) => {
78 | if (loadingFlag) {
79 | this.loading.close();
80 | }
81 | if (res.result === 0) {
82 | successFn(res);
83 | } else {
84 | const errorMsg = ErrorCode(res.result) || '服务器异常,请联系运维人员!';
85 | if (errorFn) {
86 | errorFn(errorMsg);
87 | } else {
88 | AXIOS.modalError(errorMsg);
89 | }
90 | }
91 | })
92 | .catch((err) => {
93 | if (errorFn) {
94 | errorFn(err);
95 | } else {
96 | AXIOS.modalError(err);
97 | }
98 | });
99 | }
100 |
101 | static isExisty(obj) {
102 | return obj !== null;
103 | }
104 |
105 | static modalError(message) {
106 | MessageBox.alert(message, {
107 | showConfirmButton: false,
108 | customClass: 'axios-error',
109 | center: true,
110 | type: 'error',
111 | callback: (action) => {}
112 | });
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/utils/errorcode.js:
--------------------------------------------------------------------------------
1 | const map = {
2 | 4: '服务器异常'
3 | };
4 |
5 | module.exports = function (code) {
6 | return map[code];
7 | };
8 |
--------------------------------------------------------------------------------
/src/utils/localdata.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This module is used for mock testing
3 | * add new mock data if backend haven't implement the logic yet
4 | */
5 |
6 | const localData = {
7 | 'claa/menulist': require('localData/menulist.json'),
8 | 'claa/linelist': require('localData/linelist.json')
9 | };
10 |
11 | module.exports = localData;
12 |
--------------------------------------------------------------------------------