创建node模板
特点:
1.对表单输入前端验证,使用bcrypt中间件进行后端密码加密
2.用户可通过邮箱账号进行匹配,修改密码
3.在编辑公司信息的弹窗中使用[富文本]插件,编辑内容后首页展示数据
4.使用echarts表,动态展示数据
数据大屏
定时获取新数据,进行动态展示
适配scale
countup.js实现数字滚动效果,
柱形图,雷达图,关系图,环形图,词云图,地图展示
使用数据库5.7.26
安装 npm i express -s
npm i nodemon -s 自动更新编写程序
npm install mysql 连接数据库
pnpm i cors 解决跨域请求
body-parser中间件 处理表单数据 pnpm i body-parser
bcrypt
密码加密(使数据库存的密码不是明文,以随机编码方式存) pnpm i bcryptjs
例如:明文:yan123, 随机编码:7bccfde7714a1ebadf06c5f4cea752c1
生成token中间件jsonwebtoken pnpm i jsonwebtoken
解析token中间件 express-jwt pnpm i express-jwt
接口数据的验证 pnpm install @escook/express-joi
pnpm i joi 安装Joi
---上传图像处理
pnpm i multer 此插件,用于上传头像
//1.导入node.js的crypto生成uuid(唯一标识)
const crypto = require('crypto')
//2.导入fs用于处理文件
const fs = require('fs')
有很多和上述具有相同功能的库可以选择,
前端
pnpm i vue-router@4 安装router
pnpm i element-plus
pnpm install sass-loader
pnpm install style-loader
pnpm install mitt 安装全局事件总线
pnpm install echarts
--封装svg图标
pnpm i vite-plugin-svg-icons
pnpm i fast-glob
---
pnpm i pinia
pnpm i pinia-plugin-persistedstate
---富文本
pnpm install @wangeditor/editor --save
pnpm install @wangeditor/editor-for-vue@next --save
---
pnpm install echarts
1.配环境
// 导入express框架
const express=require('express')
//创建express实例
const app=express()
// 导入cors
const cors = require('cors')
// 全局挂载
app.use(cors())
// 绑定和侦听指定的主机和端口
app.listen(3007, () => {
console.log('http://127.0.0.1:3007')
})
2.body-parser中间件 处理表单数据
// 导入express框架
const express=require('express')
//创建express实例
const app=express()
// 导入cors
const cors = require('cors')
// 全局挂载
app.use(cors())
// 导入body-parser
var bodyParser = require('body-parser')
// parse application/x-www-form-urlencoded
// 当extended为false时,值为数组或者字符串,当为ture时,值可以为任意类型
//-----------------------------------------------------------------------------------
app.use(
bodyParser.urlencoded({
extended: false,
})
)
// parse application/json
app.use(bodyParser.json())
//-----------------------------------------------------------------------------------
// 绑定和侦听指定的主机和端口
app.listen(3007, () => {
console.log('http://127.0.0.1:3007')
})
3.与数据库连接
创建db文件夹 db/index.js
// 导入mysql数据库
// npm install mysql
const mysql = require('mysql')
// 创建与数据库的连接
const db = mysql.createPool({
host:'localhost',
user:'back_system',
password:'123456',
database:'back_system'
})
// 对外暴露数据库
module.exports = db
4.路由
创建路由文件router
对路由处理文件router_handle
测试
1.登录注册接口
用户信息相关接口
1.上传头像接口
目录
router/userinfo.js
const express = require('express')
const router = express.Router()
//涉及修改密码
// .导入expreJoi接口数据的验证
const expressJoi = require('@escook/express-joi')
// 导入路由处理模块,然后去router_handle写对应处理函数
const userinfoHandler = require('../router_handle/userinfo.js')
//------------------------------------------------------------------------------------
// 路由 上传头像
router.post('/uploadAvatar',userinfoHandler.uploadAvatar)
//3.暴露路由
module.exports=router
router_handle/userinfo.js
const db = require('../db/index.js')
// 导入bcrypt加密中间件
const bcrypt = require('bcryptjs')
//导入node.js的crypto生成uuid(唯一标识)
const crypto = require('crypto')
//导入fs用于处理文件
const fs = require('fs')
exports.uploadAvatar = (req, res) => {
// res.send(req.files[0]) 返回上传图片信息 进行测试
// 1.生成olnyId随机ID,文件与用户对应
const onlyId = crypto.randomUUID()
//保存上传文件时随机生成的文件名filename,后期处理路径
let oldName = req.files[0].filename;
//在服务器中的文件名 originalname原生名字 toString('utf8')防止乱码,使用utf8编码
let newName = Buffer.from(req.files[0].originalname, 'latin1').toString('utf8')
//文件在服务器的名字进行更换
fs.renameSync('./public/upload/' + oldName, './public/upload/' + newName)
//sql语句
const sql = 'insert into image set ?'
db.query(sql, {
image_url: `http://127.0.0.1:3007/upload/${newName}`,
onlyId
}, (err, result) => {
if (err) return res.cc(err)
res.send({
onlyId,
status: 0,
url: 'http://127.0.0.1:3007/upload/' + newName
})
})
}
app.js
// 1.导入express框架
const express=require('express')
//2.创建express实例
const app=express()
//3. 导入cors
const cors = require('cors')
// 4.全局挂载
app.use(cors())
//-----------------------------------------------------------------------------------
// 7.使用multer
// Multer 是一个 node.js 中间件,用于处理 multipart/form-data 类型的表单数据,它主要用于上传文件。
const multer = require("multer");
// 在server服务端下新建一个public文件,在public文件下新建upload文件用于存放图片
const upload = multer({ dest:'./public/upload' })
//使用
app.use(upload.any())
// 静态托管,就没有public名字
app.use(express.static("./public"));
//-----------------------------------------------------------------------------------
// 5.导入body-parser
var bodyParser = require('body-parser')
// parse application/x-www-form-urlencoded
// 当extended为false时,值为数组或者字符串,当为ture时,值可以为任意类型
//-----------------------------------------------------------------------------------
app.use(
bodyParser.urlencoded({
extended: false,
})
)
// parse application/json
app.use(bodyParser.json())
//-----------------------------------------------------------------------------------
// 6.导入jwt配置文件
const jwtconfig = require('./jwt_config/index.js')
//导入jwt
const { expressjwt: jwt } = require('express-jwt')
//使用jwt中间件排除不需要在请求端发送token的接口
// app.use(jwt({
// secret:jwtconfig.jwtSecretKey,algorithms:['HS256'] //算法
// }).unless({
// path:[/^\/api\//] //注登录不需要携带token
// }))
//-----------------------------------------------------------------------------------
// 处理错误中间件在 router_handle里调用
app.use((req, res, next) => {
// status=0为成功,=1为失败,默认设为1,方便处理失败的情况
res.cc = (err, status = 1) => {
res.send({
status,
// 判断这个error是错误对象还是字符串
message: err instanceof Error ? err.message : err,
})
}
next()
})
//-----------------------------------------------------------------------------------
// 新建错误中间件,对不符合joi验证的账号密码进行报错
app.use((err, req, res, next) => {
if (err instanceof Joi.ValidationError) {
res.send({
status: 1,
message: '输入的数据不符合验证规则',
})
}
})
//-----------------------------------------------------------------------------------
// 绑定和侦听指定的主机和端口
//接口1
const loginRouter=require('./router/login.js')
//需要加前缀,本地路径访问加api前缀
app.use('/api',loginRouter)
//接口2
const userRouter=require('./router/userinfo.js')
// 挂载
app.use('/user',userRouter)
app.listen(3007, () => {
console.log('http://127.0.0.1:3007')
})
测试
真实返回
数据库里也有了
2. 绑定账号接口
onlyId与对应用户绑定头像,修改account表的image_url image表的account
router/userinfo.js
const express = require('express')
const router = express.Router()
//涉及修改密码
// .导入expreJoi接口数据的验证
const expressJoi = require('@escook/express-joi')
// 导入路由处理模块,然后去router_handle写对应处理函数
const userinfoHandler = require('../router_handle/userinfo.js')
//------------------------------------------------------------------------------------
// 路由 上传头像
router.post('/uploadAvatar',userinfoHandler.uploadAvatar)
//绑定账号
router.post('/bindAccount',userinfoHandler.bindAccount)
//3.暴露路由
module.exports=router
router_handle/userinfo.js
exports.bindAccount = (req, res) => {
const {
account,
onlyId,
url
} = req.body
const sql = 'update image set account = ? where onlyId = ?'
db.query(sql, [account, onlyId], (err, result) => {
if (err) return res.cc(err)
if (result.affectedRows == 1) {
const sql1 = 'update users set image_url = ? where account = ?'
db.query(sql1, [url, account], (err, result) => {
if (err) return res.cc(err)
res.send({
status: 0,
message: '修改成功'
})
})
}
})
}
需要三个字段 uuid由随机生成,来和账号对应,匹配对应头像,防止头像地址相同而匹配混乱
数据库
3. 获取用户信息接口
第一 当登陆成功会返回账号所有信息,把信息保存到localstorage里就可以渲染账户信息 第二 根据账号ID去数据库里查找信息(这里用第二种写的) router/userinfo.js
const express = require('express')
const router = express.Router()
//涉及修改密码
// .导入expreJoi接口数据的验证
const expressJoi = require('@escook/express-joi')
// 导入路由处理模块,然后去router_handle写对应处理函数
const userinfoHandler = require('../router_handle/userinfo.js')
//------------------------------------------------------------------------------------
// 路由 上传头像
router.post('/uploadAvatar',userinfoHandler.uploadAvatar)
//绑定账号
router.post('/bindAccount',userinfoHandler.bindAccount)
router.post('/getUserInfo',userinfoHandler.getUserInfo)
//3.暴露路由
module.exports=router
router_handle/userinfo.js
// 获取用户信息 接收参数 id
exports.getUserInfo = (req, res) => {
const sql = 'select * from users where id = ?'
db.query(sql, req.body.id, (err, result) => {
if (err) return res.cc(err)
result[0].password = ''
res.send(result[0])
})
}
查询的信息
4. 修改姓名接口
router/userinfo.js
//同上添加接口路由
router.post('/changeName',userinfoHandler.changeName)
router_handle/userinfo.js
// 修改姓名 接收参数 id name
exports.changeName = (req, res) => {
const {
id,
name
} = req.body
//根据id去users表更改name
const sql = 'update users set name = ? where id = ?'
db.query(sql, [name, id], (err, result) => {
if (err) return res.cc(err)
res.send({
status: 0,
message: '修改成功'
})
})
}
数据库
5. 修改姓名接口
router/userinfo.js
//同上添加接口路由
router.post('/changeSex',userinfoHandler.changeSex)
router_handle/userinfo.js
//5.修改性别接口
exports.changeSex = (req, res) => {
const {
id,
sex
} = req.body
//注意 参数 要与sql语句位置对应[sex,id],不能写乱了
const sql = 'update users set sex = ? where id = ?'
db.query(sql, [sex,id], (err, result) => {
if (err) return res.cc(err)
res.send({
status: 0,
message: '修改成功'
})
})
}
数据库
6. 修改邮箱接口
router_handle/userinfo.js
// 修改邮箱 接收参数 id email
exports.changeEmail = (req, res) => {
const {
id,
email
} = req.body
const sql = 'update users set email = ? where id = ?'
db.query(sql, [email, id], (err, result) => {
if (err) return res.cc(err)
res.send({
status: 0,
message: '修改成功'
})
})
}
数据库
有一些要做输入前校验
错误示例
7. 修改用户密码接口
router/userinfo.js
router_handle/userinfo.js
// 7. 修改用户密码接口
// 先输入旧密码 oldPassword 新密码 newPassword id
exports.changePassword = (req, res) => {
//通过id寻找旧密码
const sql = 'select password from users where id = ?'
db.query(sql, req.body.id, (err, result) => {
if (err) return res.cc(err)
// bcrypt
//使用加密中间件的compareSync解密方法 hashSync加密方法
//第一个参数req.body.oldPassword 前端传来的旧密码
//第二个参数result[0].password 数据库查找到的密码
const compareResult = bcrypt.compareSync(req.body.oldPassword, result[0].password)
//结果不相等
if (!compareResult) {
return res.send({
status: 1,
message: '原密码错误'
})
}
//操作成功,把新密码做加密
req.body.newPassword = bcrypt.hashSync(req.body.newPassword, 10)
//更新旧密码
const sql1 = 'update users set password = ? where id = ?'
db.query(sql1, [req.body.newPassword, req.body.id], (err, result) => {
if (err) return res.cc(err)
res.send({
status: 0,
message: '修改成功'
})
})
})
}
8. 验证账户和与邮箱是否一致接口 email account 返回对应id
router_handle/userinfo.js ``
//忘记密码-------------------------------------------------------------------------------------------根据以下接口找回
exports.verifyAccountAndEmail = (req, res) => {
const {
account,
email
} = req.body
//根据账号找邮箱 返回对应ID
const sql = 'select * from users where account = ?'
db.query(sql, account, (err, result) => {
if (err) return res.cc(err)
// res.send(result[0].email) 返回数据库中的邮箱
//对比数据库中的邮箱与前端传来的邮箱是否一直
if (email == result[0].email) {
res.send({
status: 0,
message: '查询成功',
id: result[0].id
})
} else {
res.send({
status: 1,
message: '查询失败'
})
}
})
}
9.登录页面修改密码接口 参数 newPassword id
// 9.登录页面修改密码 参数 newPassword id,在前端完成判断两次密码是否一致
exports.changePasswordInLogin = (req, res) => {
// req.body.newPassword
const user = req.body
//对传来的密码进行加密
user.newPassword = bcrypt.hashSync(user.newPassword, 10)
const sql = 'update users set password = ? where id = ?'
db.query(sql, [user.newPassword, user.id], (err, result) => {
if (err) return res.cc(err)
res.send({
status: 0,
message: '更新密码成功'
})
})
}
调用接口,前端传数据,后端去数据库查是否满足条件
查询成功返回id,进入下一步,把id携带,修改id对应的账号
首页需要的接口
轮播图及公司介绍
...................