0
点赞
收藏
分享

微信扫一扫

Vue2 + ElementUI快速搭建后台

驚鴻飛雪 2022-02-26 阅读 53

创建项目

此处不做详细描述,请参考:项目创建

添加环境变量

新建.env.development文件

VUE_APP_BASE_API = http
://localhost:3000

新建 .env.production 文件(根据项目需求,选择性创建)

VUE_APP_BASE_API = https
://api.xxx.xxx

安装基础依赖

yarn add element-ui axios moment

全局过滤器

新增 src/filters/index.js 文件

import moment from "moment";

/**
 * "Fri Dec 10 2021 01:01:49 GMT+0800 (China Standard Time)" => "2021年12月10日凌晨1点01分"
 * @param {number} num
 */
export function dateFormat(value) {
  if (!value) {
    return "";
  }

  moment.locale("zh-cn");
  return moment(value).format("LL");
}

/**
 * 10000 => "10,000"
 * @param {number} num
 */
export function thousandFormat(num) {
  const result = (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ","));
  return result + "元";
}

注册依赖

src/main.js

.
.
import
ElementUI
from
"element-ui";
import "element-ui/lib/theme-chalk/index.css";

Vue.config.productionTip = false;
Vue.use(ElementUI);

// 注册全局过滤器
import * as filters from "./filters";

Object.keys(filters).forEach((key) => {
  Vue.filter(key, filters[key]);
});
.
.

封装 axios

新增 src/utils/request.js 文件

import axios from "axios";
import { MessageBox, Message } from "element-ui";
import store from "@/store";
import { getToken } from "@/utils/auth";

// 创建axios实例
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // baseURL: "/api", // url = base url + request url
  // withCredentials: true, // 当跨域请求时,发送 cookies
  timeout: 5000, // 请求超时时间
});

// request拦截器
service.interceptors.request.use(
  (config) => {
    // do something 在发送请求前
    if (store.getters.token) {
      // 让每个请求携带token
      // ["X-Token"]为自定义key
      // 请根据实际情况自行修改
      config.headers["token"] = getToken();
    }
    return config;
  },
  (error) => {
    // do something 当请求错误
    console.log(error); // for debug
    return Promise.reject(error);
  }
);

// respone拦截器
service.interceptors.response.use(
  /**
   * 如果你想获取 http 信息,例如 headers 或 status
   * 请 return  response => response
   */

  /**
   * 下面的注释为通过response自定义code来标示请求状态,当code返回如下情况为权限有问题,登出并返回到登录页
   * 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中
   */
  (response) => {
    const res = response.data;

    // 如果返回的自定义code不是20000, 认定为error。
    if (res.code !== 20000) {
      Message({
        message: res.message || "Error",
        type: "error",
        duration: 5 * 1000,
      });

      // 50008:非法的token; 50012:其他客户端登录了;  50014:Token 过期了;
      if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
        // 重新登录
        MessageBox.confirm(
          "你已被登出,可以取消继续留在该页面,或者重新登录",
          "确定登出",
          {
            confirmButtonText: "重新登录",
            cancelButtonText: "取消",
            type: "warning",
          }
        ).then(() => {
          store.dispatch("user/resetToken").then(() => {
            // 为了重新实例化vue-router对象 避免bug
            location.reload();
          });
        });
      }
      return Promise.reject(new Error(res.message || "Error"));
    } else {
      return res;
    }
  },
  (error) => {
    console.log("err" + error); // for debug
    Message({
      message: error.message,
      type: "error",
      duration: 5 * 1000,
    });
    return Promise.reject(error);
  }
);

export default service;

由于上面 request 拦截器中读取 token 是从 cookie 中读的,所以接下来我们要配置 cookie

配置 cookie

1、装包

yarn add js-cookie

新增 src/utils/auth.js 文件

import Cookies from "js-cookie";

// cookie中key的命名
const TokenKey = "Admin-Token";

/**
 * 获取cookie中的token
 * @returns {*}
 */
export function getToken() {
  return Cookies.get(TokenKey);
}

/**
 * 设置token到cookie中
 * @param token
 * @param remember
 * @returns {*}
 */
export function setToken(token, remember = false) {
  // 记住我
  if (remember) {
    return Cookies.set(TokenKey, token, { expires: 7 })
  }

  return Cookies.set(TokenKey, token);
}

/**
 * 删除cookie中的token
 * @returns {*}
 */
export function removeToken() {
  return Cookies.remove(TokenKey);
}

CSS 文件

1、新建 src/styles/common.scss 文件

a {
    color: #1f99b0;
    text-decoration: none;
}

.clear:after {
    display: block;
    content: "clear";
    height: 0;
    clear: both;
    overflow: hidden;
    visibility: hidden;
}

2、新建 src/styles/element-ui.scss 文件

.el-menu-item.is-active {
    color: #1f99b0 !important;
}

.el-switch.is-checked .el-switch__core {
    border-color: #1f99b0 !important;
    background-color: #1f99b0 !important;
}

.el-button--primary {
    color: #fff !important;
    background-color: #1f99b0 !important;
    border-color: #1f99b0 !important;
}

.el-menu-item:focus, .el-menu-item:hover {
    background-color: #e1f0f0 !important;
}

.el-submenu__title:hover {
    background-color: #e1f0f0 !important;
}

3、新建 src/styles/layouts.scss 文件

html, body {
    height: 100%;
    margin: 0;
}

.el-container, .el-aside, .el-aside .el-col, .el-menu {
    height: 100%;
}

.el-header, .el-footer {
    background-color: #e1f0f0;
    color: #333;
    height: 60px;
    line-height: 60px;
}

.el-header {

.logo {
    height: 40px;
    margin-top: 10px;
    float: left;
}

h1 {
    margin: 0 0 0 20px;
    font-size: 18px;
    font-weight: normal;
    float: left;
    line-height: 60px;;
}

}

.el-footer {
    text-align: center;
}

.el-aside {
    background-color: #e1f0f0;
    color: #333;
    line-height: 200px;
}

.el-main {
    color: #333;
    overflow: visible;
}

4、新建 src/styles/index.scss 文件

@import './layouts.scss';
@import './common.scss';
@import './element-ui.scss';

后台首页

修改 src/views/Home.vue 文件


<template>
  <div class="home">
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>仪表盘</el-breadcrumb-item>
    </el-breadcrumb>

    <el-divider></el-divider>

    <el-card class="box-card">
      <div slot="header" class="clearfix">
        长乐未央 <br />
        是什么意思?
      </div>
      <div class="info">
        汉时,有长乐宫又有未央宫。"长乐未央"四字,常见于汉宫瓦当。
        "长乐"的"乐",最早出自周公旦制礼作"乐"的乐。"乐者,天地之和也"《礼记·乐记》,"乐"的本质是"和"。"未央"意为未尽,没有穷尽。最早出自诗经(庭燎.小雅)夜如何其?夜未央,庭燎之光。
        "长乐未央"意为永远快乐,没有穷尽。
      </div>
    </el-card>
  </div>
</template>

<script>
  export default {
    name: "Home"
  };
</script>

<style scoped lang="scss">
  .info {
    font-size: 14px;
  }
</style>

布局模板

1、新建 src/components/layouts/Aside.vue 组件

<template>
  <el-aside width="200px">
    <el-col>
      <el-menu
        :router="true"
        default-active="/"
        class="el-menu-vertical-demo"
      >
        <el-menu-item index="/">
          <i class="el-icon-pie-chart"></i>
          <span slot="title">仪表盘</span>
        </el-menu-item>

        <el-submenu index="article_manage">
          <template slot="title">
            <i class="el-icon-document"></i>
            <span>新闻管理</span>
          </template>
          <el-menu-item index="/articles">新闻</el-menu-item>
          <el-menu-item index="/articles/trash">回收站</el-menu-item>
        </el-submenu>

        <el-menu-item index="/users">
          <i class="el-icon-user"></i>
          <span slot="title">用户管理</span>
        </el-menu-item>

        <el-menu-item index="/settings">
          <i class="el-icon-setting"></i>
          <span slot="title">系统设置</span>
        </el-menu-item>
      </el-menu>
    </el-col>
  </el-aside>
</template>

2、修改 src/App.vue 文件

<template>
  <el-container>
    <el-header>
      <img src="https://images.clwy.cn/common/logo.png" alt="长乐未央Logo" class="logo">
      <h1>长乐未央后台管理</h1>
    </el-header>
    <el-container>
      <Aside />
      <el-container>
        <el-main>
          <router-view />
        </el-main>
        <el-footer>Copyright 2013-2022 CLWY Inc. All Rights Reserved.</el-footer>
      </el-container>
    </el-container>
  </el-container>
</template>

<script>
import Aside from "@/components/layouts/Aside";

export default {
  components: { Aside }
};
</script>

最后引入 css

1、修改 src/main.js 文件

import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
import "@/styles/index.scss";   // 引入所有 css

Vue.config.productionTip = false;
Vue.use(ElementUI);

// 注册全局过滤器
import * as filters from "./filters";

Object.keys(filters).forEach((key) => {
  Vue.filter(key, filters[key]);
});

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

2、修改 src/router/index.js ,将路由修改为懒加载模式

import Vue from "vue";
import VueRouter from "vue-router";

Vue.use(VueRouter);

const routes = [
  {
    path: "/",
    name: "Home",
    component: () => import("../views/Home.vue")
  }
];

const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes
});

export default router;

最终后台首页效果图如下:
在这里插入图片描述

举报

相关推荐

0 条评论