写在前面:
使用node实现后端功能是参考这篇博客写的,我对node的详细功能其实还不太清晰vue+node+mysql全栈项目完整记录_vue+nodejs+mysql项目_栀椩的博客-CSDN博客
生成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')
})
这里需要两个表,表tb_admin用于保存登录的账户信息;表tb_user用于保存用户管理页的用户信息。
在根目录下创建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文件夹用于写相关的请求函数(接收请求后的具体操作都在里面实现)
需要实现的功能:在登录页点击登录后,发送登录请求给后端,后端判断账号密码是否正确,并返回对应的菜单列表
在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)
在后端设置了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中
和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
})
都一样的,就是接口名字和之前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
})
在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
})
在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