vue2.x从零到一的搭建自己风格的后台管理系统 - 项目新建及基础配置

639 阅读3分钟

前言

入职一家新公司,报道第一天任务安排的是一个后台管理系统,项目交接给我之前,其他同事写过几个页面。这是一个船新的挑战,后台管理系统搞起。

项目搭建

npm install -g @vue/cli				// 安装新版vue脚手架
vue --version						// 检查vue版本
vue create your-project-name		// 创建项目

这里我选择了,第一个vue2,babel与eslint。

项目配置

main.js

import Vue from 'vue'
import App from './App.vue'
import axios from '@/utils/request'				// 封装axios
import router from '@/router'					// 路由管理
import store from '@/store'						// vuex状态管理
import lodash from 'lodash'						// lodash(可用可不用的js方法库)
import ElementUI from 'element-ui'				// 完整引入Element
import '../theme/index.css';
import '@/assets/css/common.less'				// 公共方法

import './permission'                   		// 权限路由控制

Vue.prototype.$axios = axios;
Vue.config.productionTip = false
Vue.use(ElementUI)
Vue.use(lodash)

new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App),
}).$mount('#app')

utils/request.js(axios封装)

import axios from "axios";
import NProgress from "nprogress";      // 进度条
import "nprogress/nprogress.css"        // 进度条样式
import { Message } from "element-ui";
import { hasToken, getToken } from "@/utils/common"
// import router from "./router"
console.log("当前环境变量:" + process.env.NODE_ENV);
console.log("当前环境路径:" + process.env.VUE_APP_URL);
const service = axios.create({
    baseURL: process.env.VUE_APP_URL,
    // timeout: 10000   // 超时时间
});
// 请求拦截器
service.interceptors.request.use(
    config => {
        NProgress.start();
        if (hasToken()) {
            config.headers["Authorization"] = getToken()
        }
        return config;
    },
    error => {
        console.log(error);
        return Promise.reject();
    }
);
// 响应拦截器
service.interceptors.response.use(
    response => {
        NProgress.done();
        if (response.status === 200) {
            return Promise.resolve(response.data);
        } else {
            Promise.reject(response.data);
        }
    },
    error => {
        NProgress.done();
        // 请求超时
        if (error.code === "ECONNABORTED" && error.message.indexOf("timeout") !== -1) {
            Message.error({
                message: "接口请求超时",
                center: true,
                showClose: true,
                duration: 2000
            });
        }
        let errorResponse = error.response;
        if (errorResponse) {
            switch (errorResponse.status) {
                case 400:
                    Message.error({
                        message: errorResponse.data.message,
                        center: true,
                        showClose: true,
                        duration: 2000
                    });  
                    break;
                case 401:
                    Message.warning({
                        message: "暂无权限",
                        center: true,
                        showClose: true,
                        duration: 2000
                    });       
                    return
                case 500:
                    Message.warning({
                        message: "服务器异常",
                        center: true,
                        showClose: true,
                        duration: 2000
                    }); 
                    return
                case 404:
                    Message.warning({
                        message: "资源未找到",
                        center: true,
                        showClose: true,
                        duration: 2000
                    }); 
                    return
            }
        }
        return Promise.reject(errorResponse.data);
    }
);
export default service;

utils/common.js(公共方法封装)

// 是否有token
export function hasToken() {
    let token = localStorage.getItem("token");
    if (token) return true
    return false
}

// 获取token
export function getToken() {
    return localStorage.getItem("token");
}

// 移除token
export function removeToken() {
    return localStorage.removeItem("token");
}

vue.config.js

module.exports = {
    publicPath:'./' ,
    devServer: {
        proxy: {
            '/api':{		// 配置代理
                target: 'http://192.168.3.20:8079',
                changeOrigin: true,
                pathRewrite: {
                	'^/api': '/api'
                }
            },
        },
        disableHostCheck: true
    },
    chainWebpack: config => {
        // 其他配置
        config.entry('main').add('babel-polyfill') // main是入口js文件
        // 其他配置
    }
};

api/login.js // 登录api接口

import request from '@/utils/request';

// 获取token 
export function login(params) {
    return request({
        url: '/auth/auth/token',
        method: 'post',
        headers: {						// 可进行headers的配置
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        params: params,					// axios参数,自动拼接在url后边,以key=value形式
        data: params,					// axios参数,在body里面
        auth: { 						// axios basic auth验证
            username: "username", 
            password: "password" 
        }
    });
}

router/index.js

import Vue from "vue";
import Router from "vue-router";
// 第三方库需要use一下才能用
Vue.use(Router)

const originalPush = Router.prototype.push
   Router.prototype.push = function push(location) {
   return originalPush.call(this, location).catch(err => err)
}
export const defaultRoutes = [
    {
      path: "/",
      component: () => import("@/views/login"),
      hidden: true,
    },
    {
        path: "/login",
        name: "登录",
        component: () => import("@/views/login"),
        meta: { title: "登录", icon: "dashboard", affix: true },
        hidden: true,
    },
    {
        path: "/stage",
        name: "平台",
        component: () => import("@/views/stage"),
        meta: { title: "平台", icon: "dashboard", affix: true },
        hidden: true,
    },
    {
        path: "/404",
        name: "404",
        component: () => import("@/views/error-page/404"),
        meta: { title: "404", icon: "dashboard", affix: true },
        hidden: true,
    },
    {
        path: "/401",
        name: "401",
        component: () => import("@/views/error-page/401"),
        meta: { title: "401", icon: "dashboard", affix: true },
        hidden: true,
    },
    {
        path: "/500",
        name: "500",
        component: () => import("@/views/error-page/500"),
        meta: { title: "500", icon: "dashboard", affix: true },
        hidden: true,
    },
    
]

const router = new Router({
    routes: defaultRoutes
});

export default router

store/index.js(状态管理)

import Vue from "vue"
import Vuex from "vuex"
import getters from "./getters"
import settings from "./modules/settings"


Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    settings,
  },
  getters
})

export default store

store/modules/settings

const state = {
    navbar: "",                 // 面包屑导航
    collapse: false             // 侧边栏是否收缩
}

const mutations = {
    CHANGE_NAVBAR: (state, name) => {
        state.navbar = name;
        sessionStorage.setItem("navbar", name);
    },
    CHANGE_COLLAPSE: (state, flag) => {
        state.collapse = flag;
    },
}

const actions = {
    changeNavbar ({ commit }, name) {
        commit("CHANGE_NAVBAR", name)
    },
    changeCollapse ({ commit }, flag) {
        console.log(flag)
        commit("CHANGE_COLLAPSE", flag)
    }
}

export default {
    namespaced: true,
    state,
    mutations,
    actions
}

结语

这次就暂时写这么多,其中代码部分是参考vue-element-admin的代码。下篇文章开始出现差异化,自定义配置页面的布局及侧边栏,面包屑导航等。