如何使用Egg.js快速搭建一个简单完整的后台管理系统

如何使用Egg.js快速搭建一个简单完整的后台管理系统

最近在学习Egg.js,它是阿里推出的基于Koa的node开发框架,是为企业级框架和应用而生;它简单且扩展性强,非常适合做个人项目。

原文参考:https://blog.csdn.net/weixin_41967475/article/details/108712277

一、egg创建项目

1.要求nodejs版本必须大于8.0并且要用LTS版本

2.全局安装egg的环境(只需安装一次)

npm i egg-init -g / cnpm i egg-init -g

3.创建项目

  1. cd 到目录里面(注意目录不要用中文,不要有空格)
  2. 创建项目:egg-init 项目名称 --type=simple ;然后一直回车即可
    如:egg-init eggdemo --type=simple
  3. cd eggdemo
  4. cnpm install / npm install
    在这里插入图片描述
    在这里插入图片描述

4.运行项目

npm run dev / cnpm run dev

在这里插入图片描述

二、router和 controller 分组

1. router分组

  1. 在app文件夹下,新建router文件夹,且在router文件夹里面再新建admin.js文件,以后主要在admin.js文件里写后台接口;如:
'use strict';
module.exports = app => {
    const { router, controller } = app;
    router.get('/', controller.home.index);
    router.get('/admin', controller.admin.main.index);
    router.get('/admin/login', controller.admin.login.index);
    router.post('/admin/doLogin', controller.admin.login.doLogin);
    router.get('/admin/loginOut', controller.admin.login.loginOut);
};

2. controller分组

在controller文件夹下,新建admin、api两个文件夹,以后主要就在admin文件里写后台系统内容,api文件里写前台内容
在这里插入图片描述

三、egg模板引擎的配置

1.egg 安装 ejs模块

cnpm install egg-view-ejs --save

2.配置模板引擎模块 >> config/plugin.js

// 第三方的ejs 模板引擎的引入
ejs: {
  enable: true,
  package: 'egg-view-ejs',
}

3.设置后缀 .html(默认 .ejs) >> config/config.default.js

// 配置模板引擎
config.view = {
  mapping: {
    '.html': 'ejs',
  },
};

4.在app文件夹下,新建一个view文件夹,以后就在view文件夹下存放后台管理系统视图模板

四、egg-mongoose 模块的配置

1.安装egg-mongoose模块

cnpm install egg-mongoose --save

2. config/plugin.js下的配置

mongoose: {
  enable: true,
  package: 'egg-mongoose'
}

3.config/config.default.js 下的配置

//配置mongoose连接mongodb数据库
//eggdemo为我在mongodb数据库创建的表
exports.mongoose = {
  client: {
    url: 'mongodb://127.0.0.1/eggdemo',
    options: {},
  }
};

4.在app文件夹下新建model文件夹,用来存放相关的集合映射

五、在mongodb中创建admin表

1.mongodb 数据中创建 eggdemo 数据库(use eggdemo)

2.新增admin集合

注:“e10adc3949ba59abbe56e057f20f883e” 是“123456”通过md5加密后得到

db.admin.insert({username:'admin',password:'e10adc3949ba59abbe56e057f20f883e'}) 

在这里插入图片描述

六、cors跨域

安装egg-cors

npm install egg-cors --save 

此时可能会报错,“egg-bin”不是内部或外部命令…
解决方法:卸载node_modules,重新cnpm install

配置egg-cors

config/plugin.js下配置:

cors: {
   enable: true,
   package: 'egg-cors',
 },

config/config.default.js下配置:

  // 配置什么域名可以访问后台服务器
  //配置允许跨域
  exports.cors = {
    // origin: '*', //任意源可访问后台服务器
    origin: 'http://localhost:8080',
    credentials: true, // 允许cookie跨越,不能写origin: '*'
    allowMethods: 'GET,PUT,POST,DELETE'
  };

七、jwt单点登录

安装jwt

npm install egg-jwt --save

配置jwt

config/plugin.js下配置:

// jwt 单点登录
jwt: {
  enable: true,
  package: "egg-jwt"
}

config/config.default.js下配置:

// JWT的原理:服务器端根据secret生成token
//即secret只有服务器端才知道是多少,也就让token只能有服务端签发
 exports.jwt = {
   secret: "myeggdemo" //自定义token的加密条件字符串
 };

前端环境中使用Vuex

1.安装Vuex
npm install vuex --save
2.新建store文件夹,并创建index.js文件
import Vue from 'vue'
import * as type from './mutations-type.js'
import storage from '@/assets/js/storage'
import Vuex from 'vuex'
Vue.use(Vuex)

export default new Vuex.Store({
  state: { // 定义数据
    token: null,
  },
  getters: { // 过滤的方法, 类似computed
    token(state) {
      state.token = storage.get('token') || ''; // 获得本地存储用户信息
      return state.token;
    },
  },
  mutations: { // 同步的提交方法(唯一修改state的方法)
    [type.SETTOKEN](state, token) {
      state.token = token;
      storage.set('token', state.token); //本地存储 token
    },

    [type.REMOVETOKEN](state) {
      state.token = '';
      storage.remove("token"); //本地移除 token 的键
    },
  },
  actions: { // 异步方法}
})

3.在main.js中全局引入
import store from './store'
4.在store文件夹下创建mutations-type.js文件
export const SETTOKEN = "setToken";
// REMOVENAME
export const REMOVETOKEN = "removeToken";

在vue中就可以通过this.setToken设置token,this.removeToken删除token

5.在assets/js文件夹下创建storage.js,对本地存储进行一个简单封装
const storage = window.localStorage;
export default {
  set(key, val) { //存
    if (val === undefined) {
      return;
    }
    storage.setItem(key, serialize(val));
  },
  get(key, def) { //获取
    const val = deserialize(storage.getItem(key));
    return val === undefined ? def : val;
  },
  remove(key) {
    //删除一个key
    storage.removeItem(key);
  },
  clear() {
    //删除整个
    storage.clear();
  }
};

function serialize(val) {
  // 存储时转字符串
  return JSON.stringify(val);
}

function deserialize(val) {
  // 获取时转为对象
  try {
    //'{"username":"tom","age":18}'
    return JSON.parse(val);
  } catch (e) {
    //如果不是对象的字符串而是纯字符串,那就不用再转对象了
    return val || undefined;
  }
}

前端环境中使用axios

1.安装axios
npm install axios --save
2.在assets/js文件夹下创建axios.js文件
import axios from 'axios'
import store from '../../store'

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'

// 请求拦截器
axios.interceptors.request.use((req) => {
 try {
 
   req.url = 'http://localhost:7001' + req.url; //拼接url
   
   if (store.getters.token) { // 将token 以http请求头形式传递给服务器
     req.headers.authorization = store.getters.token
   }
   return req;
 } catch (error) {
   console.log(error);
 }
}, (error) => {
 return Promise.reject(error);
});

// 响应拦截器
axios.interceptors.response.use(
 response => {
   return response
 },
 error => {
   if (error.response) {
     if (error.response.status == 401) {
       // token 过期本地存储删除,然后重新登录
       store.commit('removeToken')
       window.location.href = '/login'
     }
   }
   return Promise.reject(error.response.data) // 返回接口返回的错误信息
 })

src文件夹下创建api.js文件(与main.js同级)

import axios from './assets/js/axios'
// 所有接口的api封装
export default class Api {
// 获取轮播图
static carousels() {
 return axios('/api/index/carousels', 'get')
}
}
// 获取门店展示信息
static shop(page) {
  return axios(`/api/index/shop?page=${page}`, 'get')
}
//用户是否收藏
static userIsLike({
  ...args
}) {
  return axios('/api/item/userIsLike', 'post', args)
}

在vue中使用封装好的api,直接调用即可

this.Api.carousels();

后端环境中处理token

1.中间件:middleware/isLogin.js
const url = require('url')
// JWT方案
module.exports = (options, app) => {
 return async (ctx, next) => {
   let pathname = url.parse(ctx.request.url).pathname;
   // ctx.header.authorization
   let token = ctx.request.header['authorization']; //拿到前端的token  
   
   if (pathname == '/api/loginOut' || pathname == '/api/login' ||
    pathname == '/api/messageLogin'  || pathname == '/api/verify' ) {
     // 给不需要token操作的请求放行
     await next();
     
   } else {
     if (!token) {
       ctx.status = 401;
       ctx.body = {
         success: false,
         message: '没有token',
         code: -10000
       }
       return;
     } else {
     	//app.config.secret是在config/config.default.js里面自定义的token加密条件字符串
       let decode = app.jwt.verify(token, app.config.secret); //解码token
       
       let username = decode.userToken.username
       
       let hasUser = await ctx.model.User.findOne({ //数据库中获取用户名,验证是否
         username
       })
       if (hasUser) {
         //定义token解码后的用户id存为全局变量
         ctx.state.userId = decode.userToken._id;
         await next()
       } else {
         ctx.status = 401;
         ctx.body = {
           success: false,
           message: '登录过期,请重新登录',
           code: -10001 //自定义code码
         };
       }
     }
   }
 };
};

版权声明:本文为weixin_41967475原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。