NODE中间层-day6html
01-反馈前端
姓名 意见或建议
*** 今天最后一天了,刚哥讲完临走前来首歌吧,十分不舍的你。
*** 老师能不能介绍一下koa
*** 周哥今天是你最后一天了,,,难受ing 我还想听你讲一遍组件之间的传智,尤为是子传父和非父子 ..谢谢您咧❀❀❀❀node
02-回顾express
...json
中间件内代码:api
// 分类业务
const setCategory = () => {
return new Promise((resolve, reject) => {
if (req.app.locals.category) {
res.locals.category = req.app.locals.category
// 处理成功
resolve()
} else {
categoryModel.getCategory().then(data => {
// 缓存
req.app.locals.category = data
res.locals.category = data
resolve()
}).catch(err => reject(err))
}
})
}
// setCategory().then(()=>{
// next()
// }).catch(err=>next(err))
// 购物车业务
const setHeadCart = () => {
return new Promise((resolve, reject) => {
if (!req.session.user) {
const cookieString = req.cookies[cart.key] || '[]'
// [{id:100,amount:3},...]
const cartList = JSON.parse(cookieString)
const promiseArr = cartList.map(item => productModel.getProductBase(item.id))
Promise.all(promiseArr).then(results => {
// [{id:'',name:'',...},...]
// 总件数
// Array.reduce() 遍历---累加
// arr.reduce((prev,item)=>prev+item,0)
// item 遍历的时候每一项的值
// prev 上一次回调函数的返回结果
// 若是是第一次遍历 就没有上一次 最好设置一个默认值
// reduce(callback,initValue) initValue 起始值
const count = cartList.reduce((prev,item) => item.amount + prev, 0)
// 名称数组 ['名字1','名字2']
const nameList = results.map(item => item.name)
res.locals.headCart = {count, nameList}
resolve()
}).catch(err => {
reject(err)
})
} else {
cartModel.getCart(req.session.user.id).then(data => {
res.locals.headCart = {
count: data.reduce((prev,item) => item.amount + prev, 0),
nameList: data.map(item => item.name)
}
resolve()
}).catch(err => {
reject(err)
})
}
})
}
Promise.all([
setCategory(),
setHeadCart()
]).then(results => {
// 两个操做成功
// 在购物车页面 修改数量的时候 同时修改头部购物车的数量
next()
}).catch(err => {
next(err)
})
复制代码
头部代码:数组
<div class="yui3-u Right shopArea">
<div class="fr shopcar">
<div class="show-shopcar">
<span class="car"></span>
<a class="sui-btn btn-default btn-xlarge" href="/cart">
<span>个人购物车</span>
<i class="shopnum">{{headCart.count}}</i>
</a>
<div class="clearfix shopcarlist">
<ul>
{{each headCart.nameList item i}}
<li>{{item}}</li>
{{/each}}
</ul>
</div>
</div>
</div>
</div>
复制代码
// find() findIndex() includes() from() [].foreach.call( 伪数组,callback) map filter reducepromise
补充购物车数量联动头部购物车数量:缓存
// 伪数组
const $arr = $('.cart-list [type="text"]')
const headCount = [].reduce.apply($arr,[(prev,item)=>+item.value+prev,0])
$('.shopnum').html(headCount)
复制代码
03-结算-业务分析服务器
生成订单
核对订单
// 6. 提交结算数据 arr =
arr.each(function (i,item) { ids.push(item.dataset.id) }) if (!ids.length) return alert('请选择商品后去结算') location.href = '/order/add?ids=' + ids.join(',') })
04-结算-路由规则
router.get('/order/add',checkLogin, userController.orderAdd)
router.get('/checkout',checkLogin, userController.checkout)
复制代码
05-结算-生成订单
// 生成订单
exports.orderAdd = (req, res, next) => {
const items = req.query.ids
const userId = req.session.user.id
// 数据操做
userModel.createOrder(userId, items)
.then(data => {
// data 订单数据
// 未来结算页面须要根据订单编号查询订单信息
res.redirect('/checkout?num=' + data.order_number)
})
.catch(err => next(err))
}
// 生成订单
exports.checkout = (req, res, next) => {
// 渲染页面:
// a. 订单数据
// b. 收货地址列表数据
res.send('结算页面')
}
复制代码
06-结算-页面渲染
获取数据:订单数据,收货地址数据
const num = req.query.num const userId = req.session.user.id // 渲染页面: // a. 订单数据 // b. 收货地址列表数据 Promise.all([ userModel.getOrder(num), userModel.getAddressList(userId) ]).then(results=>{ res.send(results) }).catch(err=>next(err))
渲染页面
07-结算-新增收货地址
路由: /order/address post
// 让表单外的按钮去控制表单 form ----> id="addressForm"
button -----> form="addressForm" // 去掉 属性 阻止提交 data-ok="modal"
exports.orderAddressAdd = (req, res, next) => { // 添加收货地址,跳转当前的订单结算页面 // 须要数据:收件人 地址 手机号 邮编 订单编号 const {name, address, phone, code, num} = req.body userModel.addAddress(req.session.user.id, name, address, phone, code) .then(data => { res.redirect('/checkout?num=' + num) }).catch(err => next(err)) }
08-结算-选择收货地址
准备字段的值:根据收货地址数据的ID去查询
传order的num
router.get('/order/address',checkLogin, userController.orderAddressEdit) router.get('/checkout',checkLogin, userController.checkout)
exports.orderAddressEdit = (req, res, next) => { // num 订单编号 addressId 选中的收货地址数据ID const num = req.query.num const addressId = req.query.addressId const userId = req.session.user.id // 调用接口 先调用获取收货地址的接口 在去修改订单 userModel.getAddress(userId, addressId) .then(data => { // data 单条收货地址信息数据 {id,name,address,phone,code} const address = ${data.name} ${data.address} ${data.phone} ${data.code}
return userModel.editOrderAddress(num, address) }) .then(data => { // 回到结算页面 重定向 res.redirect(/checkout?num=${num}&addressId=${addressId}
) }).catch(err => next(err)) }
// 修改收货地址的时候才会传 可能没有这项数据 const addressId = req.query.addressId || ''
{{if !addressId}}
09-支付-业务分析
10-支付-了解alipay沙箱
11-支付-生成支付地址
依赖 node-alipay-sdk
var ali = new Alipay({
// 平台id
appId: '2016080300159077',
// 通知支付结果的地址
notifyUrl: 'http://www.xxx.com/callback/alipay',
// 私钥
rsaPrivate: fs.readFileSync(path.resolve('./pem/sandbox_private.pem'), 'utf-8'),
// 公钥
rsaPublic: fs.readFileSync(path.resolve('./pem/sandbox_ali_public.pem'), 'utf-8'),
// 沙箱
sandbox: true,
// 加密类型
signType: 'RSA2',
// 日志
openLog: true
});
var params = ali.pagePay({
// 品优购商品
subject: '测试商品',
// 那些商品
body: '测试商品描述',
// 平台交易编号
outTradeId: outTradeId,
// 超时时间
timeout: '10m',
// 支付的金额
amount: '10.00',
// 产品类型 0 虚拟 1 实物
goodsType: '0',
// 二维码类型
qrPayMode: 0
});
复制代码
params:加密后的传参
支付宝网关:openapi.alipaydev.com/gateway.do
最终支付的地址= 支付宝网关+ params
工具:uitl/alipay.js
12-支付-支付页面付款
<a class="sui-btn btn-danger btn-xlarge fr" href="/pay?num={{order.order_number}}">当即支付</a>
// 支付跳转
exports.pay = (req, res, next) => {
const num = req.query.num
userModel.getOrder(num)
.then(data => {
const payUrl = getPayUrl(data)
res.redirect(payUrl)
})
.catch(err => next(err))
}
复制代码
13-支付-付款成功后回跳
// 回调的地址 alipay.js
return_url: 'http://127.0.0.1:3000/pay/callback'
复制代码
14-支付-回跳后修改订单
// 支付成功后的回调
exports.callback = (req, res, next) => {
const pay_status = 1 //支付成功
const trade_no = req.query.trade_no //支付交易流水
const send_status = 0
const num = req.query.out_trade_no // 订单编号
userModel.editOrder(num, pay_status, send_status, trade_no)
.then(data=>{
// 支付成功的提示页面 包含订单信息
res.locals.order = data
res.render('callback.art')
}).catch(err=>next(err))
}
复制代码
15-支付-了解notify功能
16-扩展-自动登陆
访问该网站的时候 实现自动登陆
cookie存储 {id:'',pw:''}
前提:当前没有登陆 存储了自动登陆的信息
exports.autoLogin = (req, res, next) => { const cookieString = req.cookies[autoLoginConfig.key] if (!req.session.user && cookieString) { // 自动登陆 const autoUser = JSON.parse(cookieString) //{id,pw} userModel.getUser(autoUser.id).then(data => { if (data.password === autoUser.pw) { // 自动登陆成功 req.session.user = data next() } else { // 匹配不正确 无效信息 清除 res.cookie(autoLoginConfig.key,'') } }) } else { next() } }
17-总结
目标: