npm init -y
生成package.json
git init
git add .
git commit -m '1-项目初始化'
生成.git隐藏文件夹,新建'.gitignore'文件忽略本地仓库
npm install koa
./src/app.js
const Koa = require('koa')
const app = new Koa()
app.use((ctx, next) => {
ctx.body = 'hello!'
})
app.listen(3000, () => {
console.log('server is running on http://locahost:3000')
})
node ./src/app.js
git提交代码 git add .
npm install nodemon
package.json文件中 scripts段中添加
"scripts": {
"dev": "nodemon ./src/app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
npm install dotenv
./src/app.js
const { APP_PORT } = require('./config/config.default')
./src/config/config.default.js
const dotenv = require('dotenv')
dotenv.config()
module.exports = process.env
./.env
APP_PORT=3030
更新后的app.js
const Koa = require('koa')
const { APP_PORT } = require('./config/config.default')
const app = new Koa()
app.use((ctx, next) => {
ctx.body = 'hello!'
})
app.listen(APP_PORT, () => {
console.log('server is running on http://locahost:' + APP_PORT + '.')
})
路由:根据不同的URL,调用对应的处理函数。
npm install @koa/router
步骤: 1.导入包 2.实例化对象 3.编写路由 4.注册中间件
const Koa = require('koa');
const Router = require('@koa/router');
const { APP_PORT } = require('./config/config.default');
const app = new Koa();
const router = new Router();
router.get('/', (ctx, next) => {
ctx.body = 'hello index';
})
router.get('/pp', (ctx, next) => {
ctx.body = 'hello p';
})
app.use(router.routes())
.use(router.allowedMethods());
app.listen(APP_PORT, () => {
console.log('server is running on http://localhost:' + APP_PORT + '.')
})
代码优化 ./src/app.js
const Koa = require('koa');
const { APP_PORT } = require('./config/config.default');
const userRouter = require('./router/route')
const app = new Koa();
app.use(userRouter.routes())
.use(userRouter.allowedMethods());
app.listen(APP_PORT, () => {
console.log('server is running on http://localhost:' + APP_PORT + '.')
})
./src/router/route.js
const Router = require('@koa/router')
const router = new Router({ prefix: '/users' })
//GET /users/
router.get('/', (ctx, next) => {
ctx.body = 'hello users'
})
module.exports = router
新增./src/app/index.js
const Koa = require('koa');
const userRouter = require('../router/route')
const app = new Koa();
app.use(userRouter.routes())
.use(userRouter.allowedMethods());
module.exports = app;
优化./src/app.js=>.src/main.js
const { APP_PORT } = require('./config/config.default');
const app = require('./app');
app.listen(APP_PORT, () => {
console.log('server is running on http://localhost:' + APP_PORT + '.')
})
路由:解析URL,分布给控制器对应的方法 ./router/user.route.js
const Router = require('@koa/router')
const { register, login } = require('../controller/user.controller')
const router = new Router({ prefix: '/users' })
//GET /users/
router.get('/', (ctx, next) => {
ctx.body = 'hello users'
})
//注册接口
router.post('/register', register)
//登录接口
router.post('/login', login)
module.exports = router
./controller/user.controller.js
class UserController {
async register(ctx, next) {
console.log('注册')
ctx.body = '用户注册成功'
}
async login(ctx, next) {
console.log('登录')
ctx.body = '用户登录成功'
}
}
module.exports = new UserController()
npm install koa-body
./app/index.js
const Koa = require('koa');
const { koaBody } = require('koa-body')
const userRouter = require('../router/user.route')
const app = new Koa();
app.use(koaBody())
.use(userRouter.routes())
.use(userRouter.allowedMethods());
module.exports = app;
./controller/controller.js
class UserController {
async register(ctx, next) {
console.log('注册' + ctx.request.body)
ctx.body = ctx.request.body
}
async login(ctx, next) {
console.log('登录' + ctx.request.body)
ctx.body = ctx.request.body
}
}
module.exports = new UserController()
./service/user.service.js
class UserService {
async createUser(username, password) {
//写入数据库操作
return '注册用户写入数据库成功'
}
async loginUser(username, password) {
//写入数据库操作
return '登录成功'
}
}
module.exports = new UserService()
引用service ./controller/user.controller.js
const { createUser, loginUser } = require('../service/user.service');
class UserController {
async register(ctx, next) {
console.log('注册' + ctx.request.body)
ctx.body = ctx.request.body
//1.获取数据
const { username, password } = ctx.request.body
//2.操作数据库
const res = await createUser(username, password)
//3.返回结果
console.log(res)
}
async login(ctx, next) {
console.log('登录' + ctx.request.body)
ctx.body = ctx.request.body
//1.获取数据
const { username, password } = ctx.request.body
//2.操作数据库
const res = await loginUser(username, password)
//3.返回结果
console.log(res)
}
}
module.exports = new UserController()
sequelize ORM数据库工具
ORM:对象关系映射
- 数据表映射
- 数据表中的数据行(记录)对应一个对象
- 数据表字段对应对象的属性
- 数据表的操作对应对象的方法
npm install sequelize
npm install mysql2
新建./db/seq.js
const { Sequelize } = require('sequelize');
const { MYSQL_HOST, MYSQL_PORT, MYSQL_USER, MYSQL_PWD, MYSQL_DB } = require('../config/config.default');
// Option 3: Passing parameters separately (other dialects)
const sequelize = new Sequelize(MYSQL_DB, MYSQL_USER, MYSQL_PWD, {
host: MYSQL_HOST,
dialect: 'mysql'/* one of 'mysql' | 'postgres' | 'sqlite' | 'mariadb' | 'mssql' | 'db2' | 'snowflake' | 'oracle' */
});
sequelize.authenticate()
.then(() => {
console.log('成功了')
})
.catch(err => {
console.log('失败了')
})
module.exports = sequelize
APP_PORT = 8000
MYSQL_HOST = localhost
MYSQL_PORT = 3306
MYSQL_USER = root
MYSQL_PWD = z123456
MYSQL_DB = mydb
./model/user.model.js
const { DataType, DataTypes } = require('sequelize')
const seq = require('../db/seq')
//创建模型
const User = seq.define('user', {
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
comment: '唯一用户名'
},
password: {
type: DataTypes.TEXT,
allowNull: false,
comment: '密码'
},
role: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: 0,
comment: '是不是管理员,默认是0不同用户,1是管理员'
}
}, {
timestamps: true
})
//强制同步数据库
//User.sync({ force: true })
module.exports = User
../controller/user.controller
const { createUser, loginUser } = require('../service/user.service');
class UserController {
async register(ctx, next) {
//1.获取数据
const { username, password } = ctx.request.body
//2.操作数据库
const res = await createUser(username, password)
//3.返回结果
ctx.body = {
code: 0,
message: '用户注册成功',
result: {
id: res.id,
username: res.username
}
}
console.log(res)
}
async login(ctx, next) {
console.log('登录' + ctx.request.body)
ctx.body = ctx.request.body
//1.获取数据
const { username, password } = ctx.request.body
//2.操作数据库
const res = await loginUser(username, password)
//3.返回结果
console.log(res)
}
}
module.exports = new UserController()
../service/user.service
const User = require('../model/user.model')
class UserService {
async createUser(username, password) {
// 创建一个新用户
const res = await User.create({ username: username, password: password });
//console.log(res);
//写入数据库操作
return res.dataValues
}
async loginUser(username, password) {
//写入数据库操作
return '登录成功'
}
}
module.exports = new UserService()
../controller/user.controller.js
const { createUser, loginUser, getUserInfo } = require('../service/user.service');
async register(ctx, next) {
//1.获取数据
const { username, password } = ctx.request.body
//验证
if (!username || !password) {
console.error('用户名或密码为空', ctx.request.body)
ctx.status = 400
ctx.body = {
code: '10001',
message: '用户名或密码为空',
result: ''
}
return
}
if (getUserInfo({ username })) {
ctx.status = 409
ctx.body = {
code: '10002',
message: '用户名已经存在',
result: ''
}
return
}
//2.操作数据库
const res = await createUser(username, password)
//3.返回结果
ctx.body = {
code: 0,
message: '用户注册成功',
result: {
id: res.id,
username: res.username
}
}
console.log(res)
}
../service/user.service
async getUserInfo({ id, username, password, role }) {
const whereOpt = {}
id && Object.assign(whereOpt, { id })
username && Object.assign(whereOpt, { username })
password && Object.assign(whereOpt, { password })
role && Object.assign(whereOpt, { role })
const res = await User.findOne({
attributes: ['id', 'username', 'password', 'role'],
where: whereOpt
})
return res ? (await res).dataValues : null
}
./src/middleWare/user.middleware.js
const { getUserInfo } = require('../service/user.service')
const { userFormateError, userAlreadyExisted } = require('../constant/error.type')
const userValidator = async (ctx, next) => {
const { username, password } = ctx.request.body
//验证
if (!username || !password) {
console.error('用户名或密码为空', ctx.request.body)
ctx.app.emit('error', userFormateError, ctx)
return
}
await next();
}
const verifyUser = async (ctx, next) => {
const { username } = ctx.request.body
if (getUserInfo({ username })) {
ctx.app.emit('error', userAlreadyExisted, ctx)
return
}
await next();
}
module.exports = {
userValidator,
verifyUser
}
./src/router/user.router.js
const { userValidator, verifyUser } = require('../middleware/user.middleware')
//注册接口加入验证
router.post('/register', userValidator, verifyUser, register)
./src/constant/error.type.js
module.exports = {
userFormateError: {
code: '10001',
message: '用户名或密码为空',
result: ''
},
userAlreadyExisted: {
code: '10002',
message: '用户名已经存在',
result: ''
}
}
./src/app/index.js
const Koa = require('koa');
const { koaBody } = require('koa-body')
const userRouter = require('../router/user.route')
const app = new Koa();
const ErrorHandler = require('./errorHandler')
app.use(koaBody())
.use(userRouter.routes())
.use(userRouter.allowedMethods());
app.on('error', ErrorHandler)
module.exports = app;
./src/app/errorHandler.js
module.exports = (err, ctx) => {
let status = 500
switch (err.code) {
case '10001':
status = 400
break
case '10002':
status = 409
break
default:
status = 500
}
ctx.status = status
ctx.body = err
}
./src/controller/user.controller.js
const { getUserInfo } = require('../service/user.service')
const { userFormateError, userAlreadyExisted } = require('../constant/error.type')
const userValidator = async (ctx, next) => {
const { username, password } = ctx.request.body
//验证
if (!username || !password) {
console.error('用户名或密码为空', ctx.request.body)
ctx.app.emit('error', userFormateError, ctx)
return
}
await next();
}
const verifyUser = async (ctx, next) => {
const { username } = ctx.request.body
if (getUserInfo({ username })) {
ctx.app.emit('error', userAlreadyExisted, ctx)
return
}
await next();
}
module.exports = {
userValidator,
verifyUser
}
./src/controller/user.controller.js
async register(ctx, next) {
//1.获取数据
const { username, password } = ctx.request.body
//2.操作数据库
//增加异常捕获
try {
const res = await createUser(username1, password)
//3.返回结果
ctx.body = {
code: 0,
message: '用户注册成功',
result: {
id: res.id,
username: res.username
}
}
console.log(res)
}
catch (err) {
console.log(err)
ctx.app.emit('error', userRegisterError, ctx)
}
}
./src/constant/error.type.js
userRegisterError: {
code: '10003',
message: '用户注册失败',
result: ''
}
./src/app/errorHandler.js
case '10003':
status = 404
break
./src/controller/user.controller.js
const { userRegisterError } = require('../constant/error.type')
./src/middleware/user.middleware.js
const verifyUser = async (ctx, next) => {
const { username } = ctx.request.body
try {
const res = await getUserInfo({ username })
console.error('error:用户名已经存在', { username })
ctx.app.emit('error', userAlreadyExisted, ctx)
return
} catch (err) {
console.error('error:用户注册异常', err)
ctx.app.emit('error', userRegisterError, ctx)
}
await next();
}
将密码保存到数据库前,要对密码进行加密处理 加盐加密(加盐可以理解为私钥) 加密(salt+密码)= 密文
npm install bcryptjs
./src/controllor/user.controllor.js
const bcrypt = require('bcryptjs');
const salt = bcrypt.genSaltSync(10);
const hashPassword = bcrypt.hashSync(password, salt);
//修改
const res = await createUser(username, hashPassword)
./src/middleware/user.middleware.js
const bcrypt = require('bcryptjs');
const cryptPassword = async (ctx, next) => {
const { password } = ctx.request.body
const salt = bcrypt.genSaltSync(10);
const hashPassword = bcrypt.hashSync(password, salt);
ctx.request.body.password = hashPassword
await next();
}
module.exports = {
userValidator,
verifyUser,
cryptPassword
}
./src/router/user.router.js
const { userValidator, verifyUser, cryptPassword, verifyLogin } = require('../middleware/user.middleware')
//登录接口
router.post('/login', userValidator, verifyLogin, login)
./src/middleware/user.middleware.js
const verifyLogin = async (ctx, next) => {
const { username, password } = ctx.request.body
try {
const res = await getUserInfo({ username })
//判断登录用户名是否存在
if (!res) {
console.error('error:用户名不存在', { username })
ctx.app.emit('error', userDoesNotExisted, ctx)
return
}
//判断登录用户密码是否正确
if (!bcrypt.compareSync(password, res.password)) {
console.error('error:密码错误', { username })
ctx.app.emit('error', invalidPasswordError, ctx)
return
}
} catch (err) {
console.error('error:用户登录异常', err)
ctx.app.emit('error', userLoginError, ctx)
return
}
await next();
}
./src/constant/error.type.js
userDoesNotExisted: {
code: '10004',
message: '用户名不存在',
result: ''
},
userLoginError: {
code: '10005',
message: '用户登录异常',
result: ''
},
用户登录成功以后,给用户颁发一个令牌(token),所有后端页面的访问都需要有令牌的验证。
jwt:jsonwebtoken
- header:头部
- playload:载荷
- signature:签名
npm install jsonwebtoken
./src/controllor/user.controllor.js
var jwt = require('jsonwebtoken');
const { JWT_SECRET } = require('../config/config.default');
async login(ctx, next) {
//1.获取数据
const { username, password } = ctx.request.body
//获取用户信息(在token的playload中,记录id,username,role)
try {
//返回结果对象中,剔除password字段
const { password, ...res } = await getUserInfo({ username })
console.log(res)
ctx.body = {
code: 0,
message: '用户登录成功',
result: {
id: res.id,
username: res.username,
token: jwt.sign(res, JWT_SECRET, { expiresIn: '1d' })
}
}
} catch (err) {
console.error('用户登录失败', err)
}
}
.env
JWT_SECRET = aaaa
用户登录Test页面中
pm.test("Successful POST request", function () {
const res = pm.response.json()
pm.collectionVariables.set("token",res.result.token);
});
商城Authorization
type Bearer Token
{{token}}
variables中查看田间的token变量
./src/middleware/user.middleware.js
var jwt = require('jsonwebtoken');
const { JWT_SECRET } = require('../config/config.default');
const auth = async (ctx, next) => {
const { authorization } = ctx.request.header
const token = authorization.replace('Bearer ', '')
try {
const decoded = jwt.verify(token, JWT_SECRET);
ctx.state.user = decoded
}
catch (err) {
switch (err.name) {
case 'TokenExpiredError':
console.error('token过期了', err)
return ctx.app.emit('error', tokenExpiredError, ctx)
break
case 'JsonWebTokenError':
console.error('无效的Token', err)
return ctx.app.emit('error', jsonWebTokenError, ctx)
break
}
}
await next();
}
./src/constant/error.type.js
tokenExpiredError: {
code: '10101',
message: 'token超时',
result: ''
},
jsonWebTokenError: {
code: '10102',
message: '无效的Token',
result: ''
}
./src/router/user.router.js
//修改登录密码
router.patch('/', auth, (ctx, next) => {
console.log(ctx.state.user)
ctx.body = '登录密码修改成功'
})
./src/router/user.router.js
//修改登录密码
router.patch('/', auth,cryptPassword, (ctx, next) => {
console.log(ctx.state.user)
ctx.body = '登录密码修改成功'
})
./src/router/user.router.js
const { register, login, changePassword } = require('../controller/user.controller')
//修改登录密码
router.patch('/', auth, cryptPassword, changePassword)
./src/controllor/user.controllor.js
async changePassword(ctx, next) {
//1.获取数据
const id = ctx.state.user.id
const password = ctx.request.body.password
console.log(id, password)
//2.操作数据库
//增加异常捕获
try {
if (await updateById({ id, password })) {
//3.返回结果
ctx.body = {
code: 1,
message: '用户密码修改成功',
result: {
}
}
} else {
//3.返回结果
ctx.body = {
code: 0,
message: '用户密码修改失败',
result: {
}
}
}
}
catch (err) {
console.error(err)
ctx.app.emit('error', changePasswordError, ctx)
}
}
./scr/service/user.service.js
async updateById({ id, username, password, role }) {
const whereOpt = { id }
const newUser = {}
username && Object.assign(newUser, { username })
password && Object.assign(newUser, { password })
role && Object.assign(newUser, { role })
// 创建一个新用户
const res = await User.update(newUser, { where: whereOpt })
console.log(res.dataValues)
return res[0] > 0 ? true : false
}
./src/router/products.route.js
const Router = require('@koa/router')
const { upload } = require('../controller/products.controller')
const router = new Router({ prefix: '/products' })
router.post('/upload', upload)
./src/router/products.controller.js
const { createUser, loginUser, getUserInfo, updateById } = require('../service/user.service');
const { userRegisterError, changePasswordError } = require('../constant/error.type')
class ProductsController {
async upload(ctx, next) {
ctx.body = '商品上传成功'
}
}
module.exports = new ProductsController()
./src/router/products.route.js
const Router = require('@koa/router')
const { upload } = require('../controller/products.controller')
const router = new Router({ prefix: '/products' })
router.post('/upload', upload)
module.exports = router
./src/app/index.js
const productsRouter = require('../router/products.route')
app.use(koaBody())
.use(cors())
.use(userRouter.routes())
`.use(productsRouter.routes())`
.use(userRouter.allowedMethods());
./src/router/index.js
const fs = require('fs')
const Router = require('@koa/router')
const router = new Router()
fs.readdirSync(__dirname).forEach(file => {
if (file !== 'index.js') {
let r = require('./' + file)
router.use(r.routes())
}
})
module.exports = router
./src/app/index.js
const router = require('../router')
app.use(koaBody())
.use(cors())
.use(router.routes())
.use(router.allowedMethods());
./src/middleware/user.middleware.js
const hadAdminPermission = async (ctx, next) => {
const { role } = ctx.state.user
if (!role) {
console.error('该用户没有管理员权限')
return ctx.app.emit('error', hasAdminPermission, ctx)
}
await next();
}
module.exports = {
userValidator,
verifyUser,
cryptPassword,
verifyLogin,
auth,
hadAdminPermission
}
./src/constant/error.type.js
hasAdminPermission: {
code: '10103',
message: '没有管理员权限',
resut: ''
}
./src/router/products.route.js
const { auth, hadAdminPermission } = require('../middleware/user.middleware')
router.post('/upload', auth, hadAdminPermission, upload)
./src/middleware/auth.middleware.js
const { tokenExpiredError, jsonWebTokenError, hasAdminPermission } = require('../constant/error.type')
var jwt = require('jsonwebtoken');
const { JWT_SECRET } = require('../config/config.default');
const auth = async (ctx, next) => {
const { authorization } = ctx.request.header
const token = authorization.replace('Bearer ', '')
try {
const decoded = jwt.verify(token, JWT_SECRET);
ctx.state.user = decoded
}
catch (err) {
switch (err.name) {
case 'TokenExpiredError':
console.error('token过期了', err)
return ctx.app.emit('error', tokenExpiredError, ctx)
break
case 'JsonWebTokenError':
console.error('无效的Token', err)
return ctx.app.emit('error', jsonWebTokenError, ctx)
break
}
}
await next();
}
const hadAdminPermission = async (ctx, next) => {
const { role } = ctx.state.user
if (!role) {
console.error('该用户没有管理员权限')
return ctx.app.emit('error', hasAdminPermission, ctx)
}
await next();
}
module.exports = {
auth,
hadAdminPermission
}
./src/router/user.router.js
const { auth } = require('../middleware/auth.middleware')
./src/router/products.router.js
const { auth, hadAdminPermission } = require('../middleware/auth.middleware')
./src/app/index.js
const path = require('path')
app.use(koaBody({
multipart: true,
formidable: {//在option里的相对路径,不是相对当前的路径。是相对于Process.cwd()的相对路径
uploadDir: path.join(__dirname, '../upload'),
keepExtensions: true
}
}))
.use(cors())
.use(router.routes())
.use(router.allowedMethods());
./src/controllor/products.controllor.js
const path = require('path')
const { fileUploadError } = require('../constant/error.type')
class ProductsController {
async upload(ctx, next) {
const { file } = ctx.request.files
console.log(file.filepath)
console.log(path.basename(file.filepath))
if (file) {
ctx.body = {
code: 0,
message: '商品图片上传成功',
result: {
products_img: path.basename(file.filepath)
}
}
} else {
return ctx.app.emit('error', fileUploadError, ctx)
}
}
}
module.exports = new ProductsController()
./src/constant/error.type.js
fileUploadError: {
code: '10201',
message: '商品图片上传失败',
result: ''
}
npm i koa-static
./src/app/index.js
const koaStatic = require('koa-static')
app.use(koaStatic(path.join(__dirname, '../upload')))
./src/controllor/products.controllor.js
const { fileUploadError, unSupportedFileType } = require('../constant/error.type')
const fileTypes = ['image/jpeg', 'image/png']
if (!fileTypes.includes(file.mimetype)) {
return ctx.app.emit('error', unSupportedFileType, ctx)
}
./src/constant/error.type.js
unSupportedFileType: {
code: '10202',
message: '不支持的上传文件格式',
result: ''
}
npm install koa-parameter
./src/app/index.js
const parameter = require('koa-parameter');
app.use(parameter(app))
./src/middleware/products.middleware.js
const { productsFormatError } = require('../constant/error.type')
const validator = async (ctx, next) => {
try {
ctx.verifyParams({
products_name: { type: 'string', required: true },
products_price: { type: 'number', required: true },
products_num: { type: 'number', required: true },
products_img: { type: 'string', requited: true }
})
} catch (error) {
console.error(error)
productsFormatError.result = error
return ctx.app.emit('error', productsFormatError, ctx)
}
await next()
}
module.exports = { validator }
./src/constant/error.type
productsFormatError: {
code: '10203',
messsage: '商品参数错误',
result: ''
}
./src/router/products.router.js
router.post('/', auth, hadAdminPermission, validator, create)
./src/controller/products.controller.js
const { createProducts } = require('../service/products.service')
async create(ctx) {
try {
const { createdAt, updatedAt, ...res } = await createProducts(ctx.request.body)
ctx.body = {
code: 0,
message: '发布商品成功',
result: res,
}
}
catch (error) {
console.error(error)
return ctx.app.emit('error', publicProductsError, ctx)
}
}
./src/service/products.service.js
const Products = require('../model/products.model')
async createProducts(products) {
// 创建一个新用户
const res = await Products.create(products);
//console.log(res);
//写入数据库操作
return res.dataValues
}
module.exports = new ProductsService()
./src/model/products.model.js
const { DataTypes } = require('sequelize')
const seq = require('../db/seq')
const Products = seq.define('products', {
products_name: {
type: DataTypes.STRING,
allowNull: false,
commit: '商品名称'
},
products_price: {
type: DataTypes.DECIMAL(10, 2),
allowNull: false,
commit: '商品价格'
},
products_num: {
type: DataTypes.INTEGER,
allowNull: false,
commit: '商品库存'
},
products_img: {
type: DataTypes.STRING,
allowNull: false,
commit: '商品图片的URL地址'
}
})
//Products.sync({ force: true })
module.exports = Products
./src/constant/error.type.js
publicProductsError: {
code: '10204',
message: '发布商品错误',
result: ''
}
./src/router/products.router.js
const { upload, create, update } = require('../controller/products.controller')
router.put('/:id', auth, hadAdminPermission, validator, update)
`./src/controller/products.controller.js
async update(ctx) {
try {
const res = await updateProducts(ctx.params.id, ctx.request.body)
console.log(ctx.params)
if (res) {
ctx.body = {
code: 0,
message: '修改商品成功',
result: ''
}
}
else {
return ctx.app.emit('error', invalidProductsIDError, ctx)
}
}
catch (error) {
console.error(error)
return ctx.app.emit('error', updateProductsError, ctx)
}
}
./src/service/products.service.js
async updateProducts(id, products) {
// 更新一个用户
const res = await Products.update(products, { where: { id } });
console.log(res[0]);
//写入数据库操作
return res[0] > 0 ? true : false
}
./src/constant/error.type.js
publicProductsError: {
code: '10204',
message: '发布商品错误',
result: ''
}
./src/router/products.router.js
//修改登录密码
router.patch('/', auth, cryptPassword, changePassword)
./src/controller/products.controller.js
async remove(ctx) {
const res = await removeProducts(ctx.params.id)
//console.log(res)
ctx.body = {
code: 0,
message: '删除商品成功',
result: ''
}
}
./src/service/products.service.js
async removeProducts(id) {
const res = await Products.destroy({ where: { id } })
return res[0] > 0 ? true : false
}
./src/router/products.router.js
//标记删除接口
router.post('/:id/off', auth, hadAdminPermission, paranoid)
//标记恢复删除接口
router.post('/:id/on', auth, hadAdminPermission, unparanoid)
./src/controller/products.controller.js
async paranoid(ctx) {
const res = await paranoidProducts(ctx.params.id)
if (res) {
ctx.body = {
code: 0,
message: '下架商品成功',
result: ''
}
}
else {
return ctx.app.emit('error', invalidProductsIDError, ctx)
}
}
async unparanoid(ctx) {
const res = await unparanoidProducts(ctx.params.id)
if (res) {
ctx.body = {
code: 0,
message: '上架商品成功',
result: ''
}
}
else {
return ctx.app.emit('error', invalidProductsIDError, ctx)
}
}
./src/service/products.service.js
async paranoidProducts(id) {
const res = await Products.destroy({ where: { id } })
console.log(res)
return res > 0 ? true : false
}
async unparanoidProducts(id) {
const res = await Products.restore({ where: { id } })
console.log(res)
return res > 0 ? true : false
}
./src/router/products.router.js
//获取商品列表接口
router.get('/', findAll)
./src/controller/products.controller.js
async findAll(ctx) {
//解析PageNum和PageSize
const { PageNum = 1, PageSize = 10 } = ctx.request.query
//调用数据处理的相关方法
const res = await findProducts(PageNum, PageSize)
//返回结果
ctx.body = {
code: 0,
message: '获取商品列表成功',
result: res
}
}
./src/service/products.service.js
async findProducts(PageNum, PageSize) {
//获取商品总数
const count = await Products.count()
//获取分页的具体数据
const offset = (PageNum - 1) * PageSize
const rows = await Products.findAll({ offset: offset, limit: PageSize * 1 })
return rows
}
async findProducts(PageNum, PageSize) {
// //获取商品总数
// const count = await Products.count()
// //获取分页的具体数据
// const offset = (PageNum - 1) * PageSize
// const rows = await Products.findAll({ offset: offset, limit: PageSize * 1 })
const offset = (PageNum - 1) * PageSize
const { count, rows } = await Products.findAndCountAll({ offset: offset, limit: PageSize * 1 })
return {
PageNum,
PageSize,
total: count,
result: rows
}
}
./src/router/cart.route.js
//1.导入Kor-router
const Router = require('@koa/router')
//2.实例化router对象
const router = new Router({ prefix: '/carts' })
const { auth } = require('../middleware/auth.middleware')
const { validator } = require('../middleware/cart.middleware')
//3.编写路由规则
router.post('/', auth, validator, (ctx) => {
console.log(ctx.state.user)
ctx.body = '加入购物车成功'
})
//4.导出router对象
module.exports = router
./src/middleware/cart.middleware.js
const { invalidProductsIDError } = require('../constant/error.type')
const validator = async (ctx, next) => {
try {
ctx.verifyParams({
products_id: 'number'//简写
})
} catch (error) {
console.error(error)
invalidProductsIDError.result = error
return ctx.app.emit('error', invalidProductsIDError, ctx)
}
await next()
}
module.exports = { validator }
./src/router/cart.route.js
//3.编写路由规则
router.post('/', auth, validator, add)
./src/controller/cart.controller.js
const { createOrUpdate } = require('../service/cart.service')
class CartController {
async add(ctx) {
//将商品添加到购物车
//1、解析user_id,products_id。
const user_id = ctx.state.user.id
const products_id = ctx.request.body.products_id
//2、操作数据库
const res = await createOrUpdate(user_id, products_id)
//3、返回结果
ctx.body = {
code: 0,
message: '添加购物车成功',
result: res,
}
}
}
module.exports = new CartController()
./src/service/cart.service.js
const Cart = require('../model/cart.model')
const { Op } = require('sequelize')
class CartService {
async createOrUpdate(user_id, products_id) {
//根据user_id 和 products_id同时查找是否有记录
let res = await Cart.findOne({
where: {
[Op.and]: {
user_id,
products_id
}
}
})
if (res) {
//已经存在一条记录
await res.increment('number', { by: 1 })
return await res.reload()
}
else {
return await Cart.create({ user_id, products_id })
}
}
}
module.exports = new CartService
./src/model/cart.model.js
//1.导入sequelize的连接
const { DataTypes } = require('sequelize')
const seq = require('../db/seq')
//2.定义Cart模型
const Cart = seq.define('carts', {
products_id: {
type: DataTypes.INTEGER,
allowNull: false,
comment: '商品的ID'
},
user_id: {
type: DataTypes.INTEGER,
allowNull: false,
comment: '用户的ID'
},
number: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 1,
comment: '用户的ID'
},
selected: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true,
comment: '是否选中'
}
})
//3.同步数据
//Cart.sync({ force: true })
//4.导出Cart模型
module.exports = Cart
user表
id name age
其中id为user表的主键
class表
id userid classname
其中userid是user表的外键
const A = sequelize.define('A', /* ... */);
const B = sequelize.define('B', /* ... */);
A.hasOne(B); // A 有一个 B
A.belongsTo(B); // A 属于 B
A.hasMany(B); // A 有多个 B
A.belongsToMany(B, { through: 'C' }); // A 属于多个 B , 通过联结表 C
关联的定义顺序是有关系的. 换句话说,对于这四种情况,定义顺序很重要. 在上述所有示例中,A
称为 源 模型,而 B
称为 目标 模型. 此术语很重要.
A.hasOne(B)
关联意味着 A
和 B
之间存在一对一的关系,外键在目标模型(B
)中定义.
A.belongsTo(B)
关联意味着 A
和 B
之间存在一对一的关系,外键在源模型中定义(A
).
A.hasMany(B)
关联意味着 A
和 B
之间存在一对多关系,外键在目标模型(B
)中定义.
这三个调用将导致 Sequelize 自动将外键添加到适当的模型中(除非它们已经存在).
A.belongsToMany(B, { through: 'C' })
关联意味着将表 C
用作联结表,在 A
和 B
之间存在多对多关系. 具有外键(例如,aId
和 bId
). Sequelize 将自动创建此模型 C
(除非已经存在),并在其上定义适当的外键.
注意:在上面的 belongsToMany
示例中,字符串('C'
)被传递给 through
参数. 在这种情况下,Sequelize 会自动使用该名称生成模型. 但是,如果已经定义了模型,也可以直接传递模型.
这些是每种关联类型中涉及的主要思想. 但是,这些关系通常成对使用,以便 Sequelize 更好地使用. 这将在后文中看到.
关联 | Sequelize中文文档 | Sequelize中文网
主表调用
例如: class.belongsTo(user)
相反: user.hasOne(class)
./src/router/cart.route.js
//3.2获取购物车列表
router.get('/', auth, findAll)
./src/controller/cart.controller.js
async findAll(ctx) {
//1.解析请求参数
const { pageNum = 1, pageSize = 10 } = ctx.request.query
//2.操作数据库
const res = await findCarts(pageNum, pageSize)
//3.返回结果
ctx.body = {
code: 0,
message: '获取购物车列表成功',
result: res,
}
}
./src/service/cart.service.js
async findCarts(pageNum, pageSize) {
const offset = (pageNum - 1) * pageSize
const { count, rows } = await Cart.findAndCountAll({
attributes: ['id', 'number', 'selected'],
offset: offset,
limit: pageSize * 1
})
return {
pageNum,
pageSize,
total: count,
result: rows
}
}
./src/model/cart.model.js
`外键在cart内,所以使用belongsTo进行外键关联
相反使用hasone进行关联
`./src/model/cart.model.js
Cart.belongsTo(Products, {
foreignKey: 'products_id'
})
./src/service/cart.service.js
async findCarts(pageNum, pageSize) {
const offset = (pageNum - 1) * pageSize
const { count, rows } = await Cart.findAndCountAll({
attributes: ['id', 'number', 'selected'],
offset: offset,
limit: pageSize * 1,
include: Products
})
return {
pageNum,
pageSize,
total: count,
result: rows
}
}
product字段别名
./src/model/cart.model.js
Cart.belongsTo(Products, {
foreignKey: 'products_id',
as: 'products_info'
})
./src/service/cart.service.js
include: {
model: Products,
as: 'products_info',
attributes: ['id', 'products_name', 'products_price', 'products_img']
}
./src/middleware/cart.middleware.js
const { cartFormatError } = require('../constant/error.type')
const validator = (rules) => {
return async (ctx, next) => {
try {
ctx.verifyParams(rules)
} catch (error) {
console.error(error)
cartFormatError.result = error
return ctx.app.emit('error', cartFormatError, ctx)
}
await next()
}
}
module.exports = { validator }
./src/router/route.js
//3.1添加购物车
router.post('/', auth, validator({ products_id: 'number' }), add)
//3.3更新购物车
router.patch('/:id', auth, validator({
number: { type: 'number', required: false },
selected: { type: 'bool', required: false },
}))
./src/constant/error.type.js
cartFormatError: {
code: '10301',
message: '购物车数据格式错误',
result: ''
}
./src/router/route.js
//3.1添加购物车
router.post('/', auth, validator({ products_id: 'number' }), add)
//3.3更新购物车
router.patch('/:id', auth, update)
./src/controller/cart.controller.js
async update(ctx) {
//1.解析参数
const { id } = ctx.request.params// url中的参数
const { number, selected } = ctx.request.body//post信息中的参数
if (number === undefined && selected === undefined) {
cartFormatError.message = 'number和selected不能同时为空'
return ctx.app.emit('error', cartFormatError, ctx)
}
//2.操作数据库
const res = await updateCarts({ id, number, selected })
//3.返回数据
ctx.body = {
code: 0,
message: '更新购物车成功',
result: res
}
}
./src/service/cart.service.sj
async updateCarts(params) {
const { id, number, selected } = params
const res = await Cart.findByPk(id)
if (!res) return ''
number !== undefined ? (res.number = number) : ''
if (selected !== undefined) {
res.selected = selected
}
return await res.save()
}
./src/router/cart.route.js
//3.4删除购物车
router.delete('/', auth, validator({
ids: { type: 'array' }
}))
./scr/app/index.js
app.use(koaBody({
multipart: true,
formidable: {//在option里的相对路径,不是相对当前的路径。是相对于Process.cwd()的相对路径
uploadDir: path.join(__dirname, '../upload'),
keepExtensions: true
},
parsedMethods: ['POST', 'PUT', 'PATCH', 'DELETE']
}))
./src/controller/cart.controller.js
async remove(ctx) {
const { ids } = ctx.request.body
const res = await removeCarts(ids)
ctx.body = {
code: 0,
message: '删除购物车成功',
result: res,
}
}
./src/services/cart.services.js
async removeCarts(ids) {
return await Cart.destroy({
where: {
id: {
[Op.in]: ids,
}
}
})
}
./src/router/cart.route.js
//3.5全选
router.post('/selectAll', auth, selectAll)
//3.6全不选
router.post('/unselectAll', auth, unselectAll)
./src/controller/cart.controller.js
async selectAll(ctx) {
const user_id = ctx.state.user.id
const res = await selectAllCasts(user_id)
ctx.body = {
code: 0,
message: '全选成功',
result: res,
}
}
async unselectAll(ctx) {
const user_id = ctx.state.user.id
const res = await unselectAllCasts(user_id)
ctx.body = {
code: 0,
message: '取消全选成功',
result: res,
}
}
./src/service/cart.service.js
async selectAllCasts(user_id) {
return await Cart.update(
{ selected: true },
{
where: {
user_id
}
}
)
}
async unselectAllCasts(user_id) {
return await Cart.update(
{ selected: false },
{
where: {
user_id
}
}
)
}
./src/router/cart.route.js
//3.7获取商品总数量接口
router.get('/total', auth, getTotal)
./src/controller/cart.controller.js
async getTotal(ctx) {
console.log('111')
const user_id = ctx.state.user.id
const res = await getTotalCast(user_id)
console.log(user_id)
ctx.body = {
code: 0,
message: '获取购物车总数成功',
result: res,
}
}
./src/service/cart.services.js
async getTotalCast(user_id) {
const { count } = await Cart.findAndCountAll(
{ user_id }
)
return count
}