后端项目搭建:mpvue-shop-node
目录结构 | 说明 |
---|---|
controllers | 控制层 |
routes | 路由分发层 |
app.js | 入口文件 |
config.js | 项目配置文件 |
mysql.js | 数据库基础配置 |
新建后端项目:server
- knex 查询构造器是用于构建和执行标准的SQL查询,例如:select, insert, update, delete
- koa-bodyparser 用于解析前端发起post请求传递的数据对象
文档:https://blog.songxingguo.com/2018/06/30/knex.js-query/
cd server npm init -y npm i koa koa-router koa-bodyparser knex mysql -S
后端接收前端传递的数据方式:(重点)
// get请求,接收前端传递的数据:ctx.query.数据字段
const openId = ctx.query.openId
// post请求,接收前端传递的数据(对象):ctx.request.body
const {openId, keyword} = ctx.request.body
查询语句总结:(重点)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>查询数据>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 查询表中的所有数据
const channel = await mysql('nideshop_channel').select()
// 根据id查询表中的数据
const banner = await mysql('nideshop_ad').where({
ad_position_id: 1
}).select()
// 查询指定内容(根据id)
const newGoods = await mysql('nideshop_goods').whereIn('id', [1181000, 1135002, 1134030, 1134032]).andWhere('is_new', 1).select()
// 查询表中指定字段
const hotGoods = await mysql('nideshop_goods').column('id', 'name', 'list_pic_url', 'retail_price', 'goods_brief').where({
is_hot: 1
}).limit(5).select()
// 根据id查询表中的数据,升序,只显示4条数据
const brandList = await mysql('nideshop_brand').where({
is_new: 1
}).orderBy('new_sort_order', 'asc').limit(4).select()
// 模糊查询:用于获取用户输入的搜索关键字,显示带有关键字的搜索内容(限制10条)
const keywords = await mysql('nideshop_goods')
.column('id', 'name', 'list_pic_url', 'retail_price')
.where('name', 'like', '%' + keyword + '%').limit(10).select()
>>>>>>>>>>>>>>>>>>>>>>关联查询:表A存储值;表B存储键>>>>>>>>>>>>>>>
const attribute = await mysql('表A').column('表A.value', '表B.name').leftJoin('表B', '表A.attribute_id', '表B.id').where({
'表A.goods_id': 前端传入的查询参数goodsId
}).select()
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>插入数据>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 向数据库表中,插入指定数据
const data = await mysql('nideshop_search_history').insert({
'user_id': openId,
'keyword': keyword,
'add_time': parseInt(new Date().getTime() / 1000)
})
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>删除数据>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 根据用户标识 openId ,清除用户搜索历史记录
const data = await mysql('nideshop_search_history').where({
'user_id': openId
}).del()
console.log(data) // 显示删除的数据条数
if (data) {
ctx.body = {
'data': '清除成功'
}
} else {
ctx.body = {
'data': '清除失败'
}
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>更新数据>>>>>>>>>>>>>>>>>>>>>>>>>>
const data = await mysql('nideshop_order').where({
'user_id': openId
}).update({
user_id: openId,
goods_id: goodsId,
allprice: allPrice
})
package.json文件
{
"name": "mpvue-shop-node",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"knex": "^0.20.8",
"koa": "^2.11.0",
"koa-bodyparser": "^4.2.1",
"koa-router": "^8.0.6",
"mysql": "^2.18.1"
},
"devDependencies": {
"nodemon": "^2.0.2"
}
}
1. controllers 控制层
1-1:总布局 index.js
controllers / index.js(自动读取本地目录结构,获取文件绝对路径)
const _ = require('lodash')
const fs = require('fs')
const path = require('path')
// 映射 d 文件夹下的文件为模块
const mapDir = d => {
const tree = {}
// 获取当前文件夹下的所有文件夹和文件,分成两组,文件夹一组,文件一组
const [dirs, files] = _(fs.readdirSync(d)).partition(p => fs.statSync(path.join(d, p)).isDirectory())
// 映射文件夹
dirs.forEach(dir => {
tree[dir] = mapDir(path.join(d, dir))
});
// 映射文件
files.forEach(file => {
// 获取文件后缀名字
if (path.extname(file) === '.js') {
tree[path.basename(file, '.js')] = require(path.join(d, file))
}
})
return tree
}
// 默认导出当前文件夹下的映射
module.exports = mapDir(path.join(__dirname))
1-2:收货地址 address/ index.js
收货地址相关的接口:controllers / address/ index.js
const { mysql } = require('../../mysql')
// 获取收货地址列表
async function getListAction(ctx) {
// 第一步:接收前端传递的数据
const openId = ctx.query.openId
// 第二步:根据用户id 查询 `收货地址表`
const addressList = await mysql('nideshop_address').where({
'user_id': openId
}).orderBy('is_default', 'desc').select()
// 第三步:判断查询状态
ctx.body = {
data: addressList
}
}
// 获取详细地址
async function detailAction(ctx) {
const id = ctx.query.id
const detailData = await mysql('nideshop_address').where({
'id': id
}).select()
ctx.body = {
data: detailData[0]
}
}
// 添加或更新收货地址
async function saveAction(ctx) {
// 第一步:获取前端传递的数据
const addressId = ctx.request.body.addressId
const { userName, telNumber, address, detailaddress, checked, openId } = ctx.request.body
console.log(checked)
// 第二步:如果是默认选中,首先在数据库中查询是否是默认地址(默认收货地址只能有一个)
if (checked) {
// 首先:查询数据库中此时默认的收货地址
const isDefault = await mysql('nideshop_address').where({
'user_id': openId,
'is_default': 1
}).select()
// 然后:如果找到了这条数据,将其更改为普通收货地址
if (isDefault.length > 0) {
await mysql('nideshop_address').where({
'user_id': openId,
'is_default': 1
}).update({
'is_default': 0
})
}
}
// 收货地址不存在:说明用户新建收货地址 或者 一键导入收货地址 => 也就是要执行:添加收货地址
if (!addressId) {
// 添加地址
const data = await mysql('nideshop_address').insert({
name: userName,
mobile: telNumber,
address: address,
address_detail: detailaddress,
user_id: openId,
is_default: checked == 'true' || checked ? 1 : 0
})
// 数据添加成功-失败
if (data) {
ctx.body = {
data: true
}
} else {
ctx.body = {
data: false
}
}
} else {
// 收货地址存在:用户点击的是编辑收货地址
// 第一步:执行更新收货地址
const data = await mysql('nideshop_address').where({
'id': addressId
}).update({
name: userName,
mobile: telNumber,
address: address,
address_detail: detailaddress,
user_id: openId,
is_default: checked == 'true' || checked ? 1 : 0
})
if (data) {
ctx.body = {
data: true
}
} else {
ctx.body = {
data: false
}
}
}
}
module.exports = {
getListAction,
detailAction,
saveAction
}
1-3:购物车 cart / index.js
购物车相关的接口:controllers / cart / index.js
const { mysql } = require('../../mysql')
async function addCart(ctx) {
// 接收前端传递的数据
const { openId, goodsId, number } = ctx.request.body
/**
* 判断`购物车数据表`是否包含此数据
* 当前商品是否已加入购物车:如果有只要增加具体的数量就可以了;如果没有执行商品加入购物车的操作
*/
const haveGoods = await mysql('nideshop_cart').where({
'user_id': openId,
'goods_id': goodsId
}).select()
if (haveGoods.length === 0) {
// 根据商品id从`商品信息表`中,查询:商品的价格、商品名称、商品图片 =>然后将商品信息加入`购物车数据表`中
const goods = await mysql('nideshop_goods').where({
'id': goodsId
}).select()
const { retail_price, name, list_pic_url } = goods[0]
// 如果不存在,说明该商品没有加入购物车:将该商品加入购物车就可以了
await mysql('nideshop_cart').insert({
'user_id': openId,
'goods_id': goodsId,
number,
'goods_name': name,
retail_price,
list_pic_url
})
} else {
// 在`购物车表`中,能找到该商品。说明该商品已加入购物车 => 修改商品数量
// 第一步:查询`购物车数据表`中,该商品的数量
const oldNumber = await mysql('nideshop_cart').where({
'user_id': openId,
'goods_id': goodsId
}).column('number').select()
// 第二步:更新`购物车数据表`中的数据
await mysql('nideshop_cart').where({
'user_id': openId,
'goods_id': goodsId
}).update({
'number': oldNumber[0].number + number
})
}
// 商品加入购物车成功
ctx.body = {
data: 'success'
}
}
// 获取购物车列表
async function cartList(ctx) {
// 第一步:接收前端传递的数据
const { openId } = ctx.query
// 第二步:查询购物车表中的数据
const cartList = await mysql('nideshop_cart').where({
'user_id': openId
}).select()
ctx.body = {
data: cartList
}
}
module.exports = {
addCart,
cartList
}
1-3:商品分类 category / index.js
分类相关的接口:controllers / category / index.js
const { mysql } = require('../../mysql')
// 获取分类列表,导航栏
async function categoryNav(ctx) {
// 第一步:获取前端传递的商品分类id
const categoryId = ctx.query.id
// 第二步:获取分类(这个商品id是由前端上一个页面传递的 => 然后进入商品分类页面)
const currentNav = await mysql('nideshop_category').where({
'id': categoryId
}).select()
// 第三步:获取它的同类(是指:在首页中点击居家 =>进入商品分类页面:此时商品分类页面也要显示居家的商品分类内容)
const navData = await mysql('nideshop_category').where({
'parent_id': currentNav[0].parent_id
}).select()
ctx.body = {
navData,
currentNav: currentNav[0]
}
}
// 分类页面
async function indexAction(ctx) {
// 第一步:
const { id: categoryId } = ctx.query
// 第一步:查找 parent_id 为0的数据,作为菜单分类数据(左侧数据)
const data = await mysql('nideshop_category').where({
'parent_id': 0
}).select()
// 第二步:
const currentCategory = []
if (categoryId) {
currentCategory = await mysql('nideshop_category').where({
'parent_id': categoryId
}).select()
}
ctx.body = {
'categoryList': data
}
}
// 点击左侧菜单获取的分类商品
async function currentAction(ctx) {
// 第一步:获取商品id
const { id: categoryId } = ctx.query
// 第二步:查询`分类表`
const data = {}
const currentOne = await mysql('nideshop_category').where({
'id': categoryId
}).select()
const subList = await mysql('nideshop_category').where({
'parent_id': currentOne[0].id
}).select()
data.currentOne = currentOne[0]
data.currentOne.subList = subList
ctx.body = {
'data': data
}
}
module.exports = {
categoryNav,
indexAction,
currentAction
}
1-4:收藏 collect / index.js
收藏相关的接口:controllers / collect / index.js
const { mysql } = require('../../mysql')
// 添加收藏
async function addCollect(ctx) {
const { openId, goodsId } = ctx.request.body
// 判断是否已经收藏
const iscollect = await mysql('nideshop_collect').where({
'user_id': openId,
'value_id': goodsId
}).select()
if (iscollect.length == 0) {
await mysql('nideshop_collect').insert({
'user_id': openId,
'value_id': goodsId
})
ctx.body = {
data: 'collected'
}
} else {
await mysql('nideshop_collect').where({
'user_id': openId,
'value_id': goodsId
}).del()
ctx.body = {
data: 'uncollect'
}
}
}
module.exports = {
addCollect
}
1-5:商品 goods / index.js
商品相关的接口:controllers / goods / index.js
const { mysql } = require('../../mysql')
// 商品详情页数据
async function detailAction(ctx) {
const goodsId = ctx.query.id
const openId = ctx.query.openId
// 商品信息
const info = await mysql('nideshop_goods').where({
'id': goodsId
}).select()
// 获取商品的图片
const gallery = await mysql('nideshop_goods_gallery').where({
'goods_id': goodsId
})
// 商品参数 关联查询两张表leftJoin
/**
* 理解:这两张表都是用来形容一个人的详细信息
* A表:name id age
* B表:sex number tall
* 做法:找到A表的age18岁,然后拿着age18去找number也为18的数据
*
* 数据库表划分的非常精细:键和值分别在不同的表中
* 例如: name 对应 小明
* 表 nideshop_attribute 存放键
* 表 nideshop_goods_attribute 存放对应的值
*/
const attribute = await mysql('nideshop_goods_attribute').column('nideshop_goods_attribute.value', 'nideshop_attribute.name').leftJoin('nideshop_attribute', 'nideshop_goods_attribute.attribute_id', 'nideshop_attribute.id').where({
'nideshop_goods_attribute.goods_id': goodsId
}).select()
// 常见问题
const issue = await mysql('nideshop_goods_issue').select()
// 大家都在看
const productList = await mysql('nideshop_goods').where({
'category_id': info[0].category_id
}).select()
// 判断是否收藏过
const iscollect = await mysql('nideshop_collect').where({
'user_id': openId,
'value_id': goodsId
}).select()
let collected = false
if (iscollect.length > 0) {
collected = true
}
// 判断该用户的购物车里是否含有此商品
const oldNumber = await mysql('nideshop_cart').where({
'user_id': openId
}).column('number').select()
let allnumber = 0
if (oldNumber.length > 0) {
for (let i = 0; i < oldNumber.length; i++) {
const element = oldNumber[i] // {number: 1}
allnumber += element.number
}
}
ctx.body = {
'info': info[0] || [],
'gallery': gallery,
'attribute': attribute,
'issue': issue,
'productList': productList,
'collected': collected,
'allnumber': allnumber
}
}
// 商品列表
async function goodsList(ctx) {
// 第一步:获取分类id
const categoryId = ctx.query.categoryId
// 第二步:根据分类id,获取该商品分类所属的商品信息列表
let goodsList = []
if (categoryId) {
// 查询商品信息表
goodsList = await mysql('nideshop_goods').where({
'category_id': categoryId
}).select()
// 查询商品分类表
const currentNav = await mysql('nideshop_category').where({
'id': categoryId
}).select()
// 如果没有取到商品
if (goodsList.length == 0) {
// 找到与之相关的子类,再找到与子类相关的商品
let subIds = await mysql('nideshop_category').where({
'parent_id': categoryId
}).column('id').select()
// 如果找到了
if (subIds.length !== 0) {
subIds = subIds.map((item) => {
return item.id
})
}
goodsList = await mysql('nideshop_goods').whereIn('category_id', subIds).limit(50).select()
}
ctx.body = {
data: goodsList,
currentNav: currentNav[0]
}
}
}
module.exports = {
detailAction,
goodsList
}
1-6:首页 home / index.js
首页相关的接口:controllers / home / index.js
// 因为要查询数据库中的数据,所以引入mysql
const { mysql } = require('../../mysql')
module.exports = async (ctx) => {
// 轮播图数据
const banner = await mysql('nideshop_ad').where({
ad_position_id: 1
}).select()
// tab类型
const channel = await mysql('nideshop_channel').select()
// 品牌列表
const brandList = await mysql('nideshop_brand').where({
is_new: 1
}).orderBy('new_sort_order', 'asc').limit(4).select()
// 新品首发
const newGoods = await mysql('nideshop_goods').whereIn('id', [1181000, 1135002, 1134030, 1134032]).andWhere('is_new', 1).select()
// 人气推荐
const hotGoods = await mysql('nideshop_goods').column('id', 'name', 'list_pic_url', 'retail_price', 'goods_brief').where({
is_hot: 1
}).limit(5).select()
// 专题精选
const topicList = await mysql('nideshop_topic').limit(3).select()
// 第一步:查询标题:类别列表 **好物:查询出页面标题展示的内容
const categoryList = await mysql('nideshop_category').where({
parent_id: 0
}).select()
// 第二步:区分标题下面所属的内容:哪些内容属于居家好物一类;哪些内容属于xxx的一类,等等...
const newCategoryList = []
for (let i = 0; i < categoryList.length; i++) {
let item = categoryList[i]
let childCategoryIds = await mysql('nideshop_category').where({
parent_id: item.id
}).column('id').select()
// 变成数组的形式 [1020000, 1036002]
childCategoryIds = childCategoryIds.map((item) => {
return item.id
})
// 第三步:在商品中找到在childCategoryIds里的7条数据,whereIn 判断:category_id 是否存在于 childCategoryIds
const categoryGoods = await mysql('nideshop_goods').column('id', 'name', 'list_pic_url', 'retail_price').whereIn('category_id', childCategoryIds).limit(7).select()
newCategoryList.push({
'id': item.id,
'name': item.name,
'goodsList': categoryGoods
})
}
ctx.body = {
'banner': banner,
'channel': channel,
'brandList': brandList,
'newGoods': newGoods,
'hotGoods': hotGoods,
'topicList': topicList,
'newCategoryList': newCategoryList
}
}
1-7:订单 order / index.js
订单相关的接口:controllers / order / index.js
const { mysql } = require('../../mysql')
async function submitAction (ctx) {
// let goodsId = ctx.request.body.goodsId
// let allPrice = ctx.request.body.allPrice
// 接口前端传递的参数
const { openId, goodsId, allPrice } = ctx.request.body
// 是否存在订单
const isOrder = await mysql('nideshop_order').where({
'user_id': openId
}).select()
// 说明数据库中存在该商品--只是显示`未支付订单`--只需要更改商品信息就可以了,不需要再次插入同样的商品数据信息
if (isOrder.length > 0) {
//
const data = await mysql('nideshop_order').where({
'user_id': openId
}).update({
user_id: openId,
goods_id: goodsId,
allprice: allPrice
})
/**
* 数据更新状态:更新成功--更新失败
*/
if (data) {
ctx.body = {
data: true
}
} else {
ctx.body = {
data: false
}
}
} else {
// 说明该商品不在`未支付订单`中,说明用户要添加新的商品--直接将商品信息添加到未支付表中
const data = await mysql('nideshop_order').insert({
user_id: openId,
goods_id: goodsId,
allprice: allPrice
})
/**
* 数据添加状态:数据添加成功--数据添加失败
*/
if (data) {
ctx.body = {
data: true
}
} else {
ctx.body = {
data: false
}
}
}
}
/**
* 获取用户的收货地址
*/
async function detailAction (ctx) {
// 第一步:获取前端传递的数据:收货地址和用户标识openId
const openId = ctx.query.openId
const addressId = ctx.query.addressId || ''
// 第二步:根据openId查询订单表(未支付订单)
const orderDetail = await mysql('nideshop_order').where({
'user_id': openId
}).select()
// 第三步:如果有多个商品,就会把商品id用逗号分隔为数组,如:["1001","1002","1003"]
var goodsIds = orderDetail[0].goods_id.split(',')
// 第四步:根据用户openId 查询 `购物车表`;判断`购物车表`中的goods_id,是否存在于未支付订单表中
const list = await mysql('nideshop_cart').andWhere({
'user_id': openId
}).whereIn('goods_id', goodsIds).select()
// 第五步:收货地址
var addressList;
if (addressId) {
// 收货地址存在:查询`收货地址表`中的数据
addressList = await mysql('nideshop_address').where({
'user_id': openId,
'id': addressId
}).orderBy('is_default', 'desc').select()
} else {
// 收货地址不存在(前端没有传递收货地址)
addressList = await mysql('nideshop_address').where({
'user_id': openId
}).orderBy('is_default', 'desc').select()
}
ctx.body = {
price: orderDetail[0].allprice, // 商品单价
goodsList: list, // 商品列表
address: addressList[0] || {} // 收货地址
}
}
module.exports = {
submitAction,
detailAction
}
1-8:搜索 search / index.js
搜索相关的接口:controllers / search / index.js
const { mysql } = require('../../mysql')
/**
* 这个接口:负责搜索记录数据和热门搜索的数据
*/
async function indexAction(ctx) {
/**
* get请求,接收前端传递的数据:ctx.query.数据字段
* 传入用户的标识 openId
*/
const openId = ctx.query.openId
// 默认关键字:如果 is_default 为1,说明取出的是搜索热门的默认关键字。
const defaultKeyword = await mysql('nideshop_keywords').where({
is_default: 1
}).limit(1).select()
// 热门关键字:keyword 是指数据库中的字段
const hotKeywordList = await mysql('nideshop_keywords').distinct('keyword').column('keyword', 'is_hot').limit(10).select()
// 搜索历史(取10条):传入用户的标识 openId ,你存的数据只有你才能取出来。同理:你也不能看到别人存的数据...
const historyData = await mysql('nideshop_search_history').where({
'user_id': openId
}).limit(10).select()
ctx.body = {
'defaultKeyword': defaultKeyword[0],
'hotKeywordList': hotKeywordList,
'historyData': historyData
}
}
// 搜索时匹配搜索相关的内容
async function helperAction(ctx) {
// 获取用户搜索的内容
const keyword = ctx.query.keyword
var order = ctx.query.order
if (!order) {
order = ''
orderBy = 'id'
} else {
orderBy = 'retail_price'
}
// 查询搜索关键字
const keywords = await mysql('nideshop_goods').orderBy(orderBy, order)
.column('id', 'name', 'list_pic_url', 'retail_price')
.where('name', 'like', '%' + keyword + '%').limit(10).select()
if (keywords) {
ctx.body = {
keywords
}
} else {
ctx.body = {
keywords: []
}
}
}
// 添加搜索历史
async function addHistoryAction(ctx) {
// post请求,接收前端传递的数据(对象):ctx.request.body
const {openId, keyword} = ctx.request.body
// 查询历史搜索记录
const oldData = await mysql('nideshop_search_history').where({
'user_id': openId,
'keyword': keyword
})
/**
* 如果用户搜索的内容,已存在数据库中。则不需要重复存储搜索记录。
* 目的:判断当下搜索字段,是否插入数据库表中,作为历史搜索记录。
*/
if (oldData.length == 0) {
// 如果搜索内容,在数据库搜索历史表中找不到。则将用户搜索内容保存在数据库表中
const data = await mysql('nideshop_search_history').insert({
'user_id': openId,
'keyword': keyword,
'add_time': parseInt(new Date().getTime() / 1000)
})
// 如果data值存在,说明数据插入成功;否则数据插入失败。
if (data) {
ctx.body = {
data: 'success'
}
} else {
ctx.body = {
data: 'fail'
}
}
} else {
ctx.body = {
data: '已经有记录了'
}
}
}
// 清除历史记录
async function clearHistoryAction(ctx) {
// 获取前端传递的用户标识 openId
const openId = ctx.request.body.openId
const data = await mysql('nideshop_search_history').where({
'user_id': openId
}).del()
if (data) {
ctx.body = {
'data': '清除成功'
}
} else {
ctx.body = {
'data': null
}
}
}
module.exports = {
indexAction,
addHistoryAction,
clearHistoryAction,
helperAction
}
1-9:专题 topic / index.js
专题接口相关的接口:controllers / topic / index.js
const { mysql } = require('../../mysql')
// 获取专题列表数据
async function listAction (ctx) {
// 第一步:获取请求第几页数据(默认第一页)
let page = ctx.query.page || 1
// 第二步:每页显示多少条数据
const size = 5
// 第三步:分页处理
const data = await mysql('nideshop_topic').column('id', 'title', 'price_info', 'scene_pic_url', 'subtitle').limit(size).offset((page - 1) * size)
const data1 = await mysql('nideshop_topic').column('id', 'title', 'price_info', 'subtitle').select()
// 计算:总页数
const total = parseInt(data1.length / 5)
ctx.body = {
'page': page,
'total': total,
'data': data
}
}
// 专题详情
async function detailAction (ctx) {
// 第一步:获取前端传递的商品专题id
const id = ctx.query.id
// 第二步:
let data = []
if (id) {
data = await mysql('nideshop_topic').where({
'id': id
}).select()
}
const recommendList = await mysql('nideshop_topic').column('id', 'title', 'price_info', 'scene_pic_url', 'subtitle').limit(4).select()
ctx.body = {
'data': data[0],
'recommendList': recommendList
}
}
module.exports = {
listAction,
detailAction
}
2. 路由 routes / index.js
// prefix 表示路由前缀
const router = require('koa-router')({
prefix: '/lm'
})
const controllers = require('../controllers/index')
// 首页相关的接口
router.get('/index/index', controllers.home.index)
// 分类相关的接口
router.get('/category/categoryNav', controllers.category.index.categoryNav)
router.get('/category/indexaction', controllers.category.index.indexAction)
router.get('/category/currentaction', controllers.category.index.currentAction)
// 搜索相关的接口
router.get('/search/indexaction', controllers.search.index.indexAction)
router.post('/search/addhistoryaction', controllers.search.index.addHistoryAction)
router.post('/search/clearhistoryAction', controllers.search.index.clearHistoryAction) // 清除搜索历史
router.get('/search/helperaction', controllers.search.index.helperAction) // 搜索提示
// 商品
router.get('/goods/detailaction', controllers.goods.index.detailAction)
router.get('/goods/goodsList', controllers.goods.index.goodsList)
// 收藏相关的接口
router.post('/collect/addcollect', controllers.collect.index.addCollect)
// 订单相关的接口
router.post('/order/submitAction', controllers.order.index.submitAction)
router.get('/order/detailAction', controllers.order.index.detailAction)
// 购物车相关的接口
router.post('cart/addCart', controllers.cart.index.addCart)
router.get('/cart/cartList', controllers.cart.index.cartList)
// 收货地址相关的接口
router.get('/address/getListAction', controllers.address.index.getListAction)
router.get('/address/detailAction', controllers.address.index.detailAction)
router.post('/address/saveAction', controllers.address.index.saveAction)
// 专题接口
router.get('/topic/listaction', controllers.topic.index.listAction)
router.get('/topic/detailaction', controllers.topic.index.detailAction)
module.exports = router
3. 启动文件 app.js
const Koa = require('koa')
const app = new Koa()
const bodyParser = require('koa-bodyparser')
const config = require('./config')
// 解析请求体
app.use(bodyParser())
const router = require('./routes')
app.use(router.routes())
app.listen(config.port, () => {
console.log(`server is started at port ${config.port}`)
})
4. 配置文件 config.js
const CONF = {
port: '5757',
mysql: {
host: 'localhost',
port: 3306,
user: 'mpvue_shop',
db: 'nodemysql',
pass: 'mpvue_shop123',
char: 'utf8mb4'
}
}
module.exports = CONF
5. 数据库 mysql.js
// 获取基础配置
const configs = require('./config')
var knex = require('knex') ({
client: 'mysql',
connection: {
host: configs.mysql.host,
port: configs.mysql.port,
user: configs.mysql.user,
password: configs.mysql.pass,
database: configs.mysql.db,
}
})
// 将基础配置和sdk.config 合并 导出初始化完成的sdk
module.exports = { mysql: knex }
6. 网易严选 - 数据库表
需要自己手动导入 ,如:
PHPstudy软件