Vue3通用后台管理系统(四):使用Nodejs实现后端功能

本文详细介绍了使用Node.js、Express、MySQL构建后端,包括基础框架搭建、登录验证、用户管理(包括增删改查)以及前后端接口的连接。作者通过实例展示了如何设置JWTtoken进行安全验证和处理跨域问题。
摘要由CSDN通过智能技术生成

写在前面:

使用node实现后端功能是参考这篇博客写的,我对node的详细功能其实还不太清晰vue+node+mysql全栈项目完整记录_vue+nodejs+mysql项目_栀椩的博客-CSDN博客

(一)后端基础框架搭建

1.nodejs搭建

创建后端项目

生成package文件

npm init -y

需要使用的包如下:

"dependencies": {
    "bcryptjs": "^2.4.3",
    "cors": "^2.8.5",
    "express": "^4.18.2",
    "jsonwebtoken": "^9.0.2",
    "mockjs": "^1.1.0",
    "mysql": "^2.18.1",
    "svg-captcha": "^1.4.0"
  }

创建入口文件

api根目录下创建app.js文件,在app.js中填入以下代码

const app = express()
// 允许跨域
app.use(cors())
app.use(express.urlencoded({ extended: false }))
app.use(bodyParser.json())

// 监听5002端口
app.listen(5002, () => {
    console.log('api server running at http://127.0.0.1:5002')
})

2.数据库搭建

mysql建表 

这里需要两个表,表tb_admin用于保存登录的账户信息;表tb_user用于保存用户管理页的用户信息。

在node里引入数据库

在根目录下创建database/index.js文件

const mysql = require('mysql');

db = mysql.createPool({
    host: '127.0.0.1',
    user: 'root',
    password: '654008',  // 这里使用自己数据库的密码
    database: 'adminsystem'
})

module.exports = db

(二)登录页面后端功能 

先在根目录建立两个文件夹,router文件夹用于写相关的接口请求,router_handle文件夹用于写相关的请求函数(接收请求后的具体操作都在里面实现)

需要实现的功能:在登录页点击登录后,发送登录请求给后端,后端判断账号密码是否正确,并返回对应的菜单列表

1.配置后端 

在router文件夹中建立permit.js用于写登录相关的接口请求;在router_handle文件夹中建立permit.js用于书写对应router/permit.js的具体请求函数

在router_handle/permit.js中:

// 编写permit相关的请求函数
const db = require("../database/index");
// 生成token的密钥配置
const config = require("../config");
// 用于生成token
const jwt = require("jsonwebtoken");

// 管理员看到的菜单
const admiMenuListData = [
    {
        path: "/",
        name: "home",
        label: "首页",
        icon: "house",
        url: "Home/Home",
    },
    ...
]
// 普通用户看到的菜单
const normalMenuListData = [
    ...
]

// 登录
// 登录成功发送对应menulist
exports.login = (req, res) => {
    const { name, password } = req.body
    const sql = `select * from tb_admin where name = "${name}"`;
    // 数据库查询
    db.query(sql, (err, results) => {
        if (err) return res.status(400).json(err);

        if (results.length !== 1) return res.status(400).json("用户不存在");

        if (results[0].password != password) {
            return res.status(400).json("用户名或密码错误,请重新输入");
        }

        const user_info = {
            name: results[0].name,
        }
        // 生成token
        const tokenStr = jwt.sign(user_info, config.jwtSecretKey, {
            expiresIn: "10h",
        })

        // 传递对应的menulist
        let menuList = []
        if (results[0].key == 1) {
            menuList = admiMenuListData
        } else {
            menuList = normalMenuListData
        }

        res.json({
            status: 200,
            message: "登录成功",
            data: {
                menuList,
                token: tokenStr
            }
        })
    })
}

在根目录中创建config.js用于配置JWT的密钥

在router/permit.js中:

// 编写登录相关的接口请求
const { urlencoded } = require('express');
const express = require('express');
const router = express.Router();

const permitHandler = require('../router_handle/permit')

// 登录接口请求
router.post('/login', permitHandler.login)

module.exports = router

在app.js里配置router

const permitRouter = require('./router/permit')
app.use('/api/permit', permitRouter)

2.与前端连接

在后端设置了api访问接口地址为:http://localhost:5002

因此发起登录请求的路径为:/api/permit/login

将前端项目中的vite.config.ts中的跨域配置修改如下:

server: {
    //用来配置跨域
    host: '127.0.0.1',
    port: 5173,
    proxy: { // 配置代理
      '/api': {
        target: 'http://127.0.0.1:5002', //目标url
        changeOrigin: true // 支持跨域
      }
    }
  }

在api/index.ts中,login请求改为ajax.ts的request方法,不再使用mockRequest方法

在api/index中:
export const login = (data: any) => requests({
    url: '/permit/login',
    method: 'post',
    data
})

(三)用户管理页面后端功能

和登录请求的操作一样,先分别在router和router_handle文件夹里创建user.js文件用于实现用户管理相关的请求操作

再将接口添加到app,js中

1.查询用户数据

配置后端

和mock请求的操作一样,从数据库查询userLIst,再根据传入的关键字、页数、每页最大数来返回对应的部分数据

在router_handle/user.js中:

// 编写user相关的请求函数
const db = require("../database/index");
// 用于解析在路径中传输的参数
const url = require('url');
//引入mock模块
const Mock = require('mockjs');

exports.getUserList = (req, res) => {
    let keyword = url.parse(req.url, true).query.keyword || ''
    let page = url.parse(req.url, true).query.page || 1
    let limit = url.parse(req.url, true).query.limit || 13

    const sql = "select * from tb_user"
    // 数据库查询
    db.query(sql, (err, results) => {
        if (err) return res.status(400).json(err);
        // 判断有无关键字并返回对应有关键字的数组
        let pageList = results.filter((item) => {
            if (keyword && item.name.indexOf(keyword) === -1 && item.addr.indexOf(keyword) === -1) return false
            return true
        })
        // 分页展示
        let list = pageList.filter((item, index) => {
            return index >= (page - 1) * limit && index < page * limit
        })
        res.json({
            status: 200,
            message: "查询成功",
            data: {
                userList: list,
                total: pageList.length
            }
        })
    })
}

 在router/user.js中:

// 编写user相关的接口请求
const { urlencoded } = require('express');
const express = require('express');
const router = express.Router();

const userHandler = require('../router_handle/user')

// 查询userlist接口请求
router.get('/getuserlist', userHandler.getUserList)
// 请求添加用户数据
router.post('/adduser', userHandler.addUser)
// 请求修改用户数据 根据id
router.post('/updateuser', userHandler.updateUser)
// 请求删除用户数据 根据id
router.delete('/deleteuser', userHandler.deleteUser)

module.exports = router

与前端连接

一样的操作,查询接口为:/api/user/getuserlist

在api/index中:
export const getUserList = (params: any) => requests({
    url: 'user/getuserlist',
    method: 'get',
    params
})

2.新增用户

配置后端

都一样的,就是接口名字和之前mock的时候不太一致,不多说了

这里需要使用Mock.Random来给新增用户添加id

在router_handle/user.js中:

exports.addUser = (req, res) => {
    let user = req.body
    let userli = {
        id: Mock.Random.guid(),
        ...user
    }

    const sql = "insert into tb_user set ?";
    db.query(sql, userli, (err, results) => {
        if (err) return res.status(400).json(err);

        res.json({
            status: 200,
            message: '添加成功',
            result: user,
        })
    })
}

与前端连接

export const adduserlist = (data: any) => requests({
    url: '/user/adduser',
    method: 'post',
    data
})

3.修改用户

配置后端

在router_handle/user.js中:

exports.updateUser = (req, res) => {
    let user = req.body
    const sql = 'update tb_user set ? where id= ?'
    db.query(sql, [user, user.id], (err, result) => {
        if (err) return res.status(400).json(err);
        // 被影响的列数
        if (result.affectedRows !== 1) return res.status(400).json("添加失败");

        res.json({
            status: 200,
            message: '添加成功',
            result: user
        })
    })
}

连接前端

// 请求修改用户数据
export const updateUserList = (data: any) => requests({
    url: '/user/updateuser',
    method: 'post',
    data
})

4.删除用户

配置后端

在router_handle/user.js中:

exports.deleteUser = (req, res) => {
    let { id } = req.body
    const sql = 'delete from tb_user where id = ?'
    db.query(sql, id, (err, result) => {
        if (err) return res.status(400).json(err);
        if (result.affectedRows !== 1) return res.status(401).json("删除失败")
        res.status(200).json("删除成功")
    })
}

连接前端

// 请求删除用户数据 根据id删除
export const deleteUserList = (data: any) => requests({
    url: '/user/deleteuser',
    method: 'delete',
    data
})

(四)结束

主页的表格、图表这些数据不想写后端了,感觉都是差不多步骤

这次学习让我对node做后端更加清晰了,有种 “噢原来是这样实现前后端连接的” 的感觉,还算是蛮有收获。JWT_token什么的,感觉蛮必要的,但是这样跟着抄了一下还是不太清楚,计算机网络我根本没学好!!累死了,买本计网看看吧

这个后台管理项目太简单了点,不该现在做的(应该更早的时候做),不过人手一个的后台管理系统还是得安排上嘛,坑坑踩完了路才好走啊。

接下来到底该做什么项目啊。。是浅浅学点uniapp做个简单小程序还是继续做个难点的vue3项目啊。。好困难,准备学学webpack了,可能再重新回味下数据结构,边学边看到底该做什么项目吧。。QAQ

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个系统其实是出于学习nodejs的目的而改写的系统。 原来的系统前端使用了extjs4.2.1,后端使用了PHP5.4和ZEND框架开发,后台数据库是用mongodb2.2.2。 我抽离出了原来系统的账户管理,角色管理,菜单管理,权限管理这4个部分, 我想这4个部分,基本上所有的系统都会用到。具有一定的普遍性。所以将这4个部分用nodejs重新改写了。 该系统目前使用模块有express,ejs,connect-mongo,mongodb,express-partials,connect-flash,fibers,wind等 其实wind模块这次系统没有使用。可以将它排除出去。我是出于学习wind的目的,才加入这个模块的。 本来准备使用wind模块,是为了实现同步的目的,由于后来改用了fibers模块之后,就没有使用它。这里说明一下 不是fibers要比wind好,而是我暂时不能理解wind,或则是说对wind的研究不够吧。 众所周知nodejs是推崇异步模式。但是这个系统是从php过来的,而php的代码是同步模式的写法,所以为了在改写的过程 希望 1是代码改动最少 2是同步写法更加适合思维习惯。而且代码可读性高的目的,用到了fibers。 这个系统的源代码有些js文件里保留了一些原来的PHP代码,这是出于代码对比的目的。 是让大家了解原来的php代码是怎么实现的,用nodejs之后是如何改写的。通过对比,大家会发现 其实通过使用fibers之后,几乎两者是一模一样的。 还有源代码还保留了一些被注释掉的函数,有些是用到了wind,有些是用到了fibers,有些是直接异步的写法。 这些内容都是在开发过程我不断尝试后的产物。我花了1周的时间才实现了一个递归的调用,而且还是同步的方式。 到目前为止,我还不能理解在异步模式下实现递归调用函数。比如说源代码有个函数getMenuTree,菜单下面可能有子菜单, 子菜单的下面可能还有菜单。所以是一个递归的过程。我现在是同步的写法实现了这个函数,如果有人能够提供异步写法实现的递归函数并 emai给我,我不胜荣幸。 在使用本系统之前,必须要安装nodejs 0.10.10,mongodb2.2.2,python2.7.5至于安装的方法请googel解决。 将源代码下载之后,解压到某个目录下,比如说d:\nodejs\umav4simple目录。 进入到那个目录, a)运行以下命令 npm install express npm install ejs npm install connect-mongo npm install mongodb npm install express-partials npm install connect-flash npm install fibers npm install wind 尽管在源代码已包含了这些模块,但是最好还是要重新运行一遍。 因为有些模块可能需要重新的编译。 比如说fibers模块,我在window下运行npm install fibers的时候编译了一个win32-ia32-v8-3.14 而在linux下重新编译了linux-ia32-v8-3.14。所以说根据操作系统的不同,可能会有一些不同。 以免造成想不到的错误。 b)打开settings.js,并且将你的mongodb的设置改写并保存。 c)运行node app.js或则node cluster.js 如果没有提示错误的话,那么就说明环境配置成功了。 d)通过以下的URL可以在mongodb追加一些数据,不过只能运行一次。否则会重复追加数据。 浏览器上输入 http://localhost:3000/admin/index/install 做完之后, 浏览器上输入http://localhost:3000/ 就通过用户名admin 密码adminadmin进行登录,并使用这个系统了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值