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-總結
目標: