Authored by 周少峰

home index async

{
"extends": "yoho",
"parserOptions": {
"sourceType": "module"
"sourceType": "module",
"ecmaVersion": 2017
}
}
\ No newline at end of file
... ...
... ... @@ -14,8 +14,20 @@ const getCommonHeader = (req, res, next) => {
}).catch(next);
};
const getCommonHeaderNew = (req, res, next) => {
let channel = req.query.channel;
let uid = req.user.uid;
let clientService = _.get(req.app.locals.pc, 'clientService.new', false);
let result = req.ctx(headerModel).getHomeNavNew(uid, channel, req.originalUrl, clientService);
_.merge(res.locals, result);
next();
};
module.exports = {
getCommonHeader
getCommonHeader,
getCommonHeaderNew
};
... ...
'use strict';
const indexService = require('../models/index-service');
const _ = require('lodash');
const index = (req, res, next)=>{
let uid = req.user.uid;
... ... @@ -8,17 +9,61 @@ const index = (req, res, next)=>{
let channel = req.yoho.channel;
let isStudent = req.user.isStudent;
req.ctx(indexService).index(uid, udid, channel, isStudent).then(result => {
req.ctx(indexService).indexNew(uid, udid, channel, isStudent).then(result => {
_.merge(res.locals, result.header);
return res.render('index', {
module: 'home',
page: 'index',
meIndexPage: true,
me: result
me: result.content
});
}).catch(next);
};
// 个人中心-首页-喜欢的品牌
async function brands(req, res) {
let brandsData = await req.ctx(indexService).brands();
res.json({brands: brandsData, more: '/brands'});
}
// 新品上架
async function newArrive(req, res) {
let arrive = await req.ctx(indexService).newArrive();
res.json({newArrive: arrive});
}
// 推荐
async function recommend(req, res) {
let uid = req.user.uid;
let udid = req.user.uid + req.yoho.udid;
let channelNum = req.yoho.channelNum;
res.json({recommend: await req.ctx(indexService).recommend(uid, udid, channelNum)});
}
// 头像和左侧菜单我的消息
async function newsAvatar(req, res) {
let uid = req.user.uid;
let result = await req.ctx(indexService).newsAvatar(uid);
res.json(result);
}
async function numbers(req, res) {
let uid = req.user.uid;
let result = await req.ctx(indexService).numbers(uid);
res.json(result);
}
module.exports = {
index
index,
brands,
newArrive,
recommend,
newsAvatar,
numbers
};
... ...
... ... @@ -149,6 +149,43 @@ module.exports = class extends global.yoho.BaseModel {
});
}
getHomeNavNew(uid, channel, url, clientSwitcher) {
let navs = this._getActiveNav(url, clientSwitcher, 1);
let activeNav = navs.activeNav;
let bread = [{href: helpers.urlFormat('/'), name: 'YOHO!BUY 有货首页'}];
if (activeNav) {
bread.push({
name: '个人中心',
href: helpers.urlFormat('/home')
});
bread.push({
name: activeNav.name
});
// 订单详情
if (activeNav.curHref === '/home/orders/detail') {
Object.assign(_.last(bread), {
href: helpers.urlFormat('/home/orders')
});
bread.push({
name: '订单详情'
});
}
} else {
bread.push({
name: '个人中心'
});
}
return {
path: bread,
homeNav: navs.homeNav,
userThumb: ''
};
}
getHomeNav(uid, channel, url, clientSwitcher) {
let that = this;
... ...
... ... @@ -38,7 +38,7 @@ module.exports = class extends global.yoho.BaseModel {
method: 'web.search.favorBrand'
};
return this.get({data: options});
return this.get({data: options, param: {cache: 86400}});
}
newArrival() {
... ... @@ -84,13 +84,13 @@ module.exports = class extends global.yoho.BaseModel {
* @param string $mode
* @return mixed
*/
getByNodeContent(node, mode) {
getByNodeContent(node, mode, params) {
let options = {
method: 'web.html.content',
mode: mode,
node: node
};
return this.get({data: options});
return this.get({data: options, param: params || {}});
}
};
... ...
... ... @@ -9,6 +9,20 @@ const helpers = global.yoho.helpers;
const OrderService = require('./orders-service');
const IndexApi = require('./index-api');
const UserApi = require('./user-api');
const MsgApi = require('./message');
const headerModel = require('../../../doraemon/models/header');
const cache = global.yoho.cache;
const cachePreKey = 'HOME_INDEX_';
const defaultAvatar = '//img10.static.yhbimg.com/headimg/' +
'2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
const numbersKey = {
pending: 'pengding',
unread: 'unread',
needComment: 'needComment'
};
const CHANNEL_NUM = {
boys: 1,
... ... @@ -164,7 +178,7 @@ module.exports = class extends global.yoho.BaseModel {
_footerBanner() {
const CODE = '20110609-152143';
return new IndexApi(this.ctx).getByNodeContent(CODE).then(banner => {
return new IndexApi(this.ctx).getByNodeContent(CODE, {}, {cache: 86400}).then(banner => {
return _.get(banner, 'data', '').replace(/http:\/\//g, '//');
});
}
... ... @@ -176,6 +190,126 @@ module.exports = class extends global.yoho.BaseModel {
return new OrderService(this.ctx).closeReason();
}
// 个人中心首页 异步获取新品上架数据
async newArrive() {
let arriveCaceKey = `${cachePreKey}arrive`;
let arrive = await cache.get(arriveCaceKey);
if (!arrive) {
let arriveOrigin = await new IndexApi(this.ctx).newArrival();
arrive = this._handleProduct(_.get(arriveOrigin, 'data.product_list', []));
if (!_.isEmpty(arrive)) {
cache.set(arriveCaceKey, arrive, 3600);
}
} else {
arrive = JSON.parse(arrive);
}
return Promise.resolve(arrive);
}
// 推荐数据
async recommend(uid, udid, channelNum) {
let recommendCaceKey = `${cachePreKey}recommend`;
let recommend = await cache.get(recommendCaceKey);
if (!recommend) {
let recommendOrigin = await new IndexApi(this.ctx).recommend(channelNum, uid, udid, '100004', 30);
recommend = this._handleProduct(_.get(recommendOrigin, 'data.product_list', []));
if (!_.isEmpty(recommend)) {
cache.set(recommendCaceKey, recommend, 3600);
}
} else {
recommend = JSON.parse(recommend);
}
return Promise.resolve(recommend);
}
// 个人中心首页 异步获取品牌数据
async brands() {
let brandsCaceKey = `${cachePreKey}brands`;
let brand = await cache.get(brandsCaceKey);
if (!brand) {
let brandOrigin = await new IndexApi(this.ctx).guessBrand();
brand = this._handleBrand(_.get(brandOrigin, 'data', []), 6);
if (!_.isEmpty(brand)) {
cache.set(brandsCaceKey, brand, 86400);
}
} else {
brand = JSON.parse(brand);
}
return Promise.resolve(brand);
}
// 个人中心异步查询我的消息和头像
async newsAvatar(uid) {
let result = await Promise.props(
{
profile: new UserApi(this.ctx).getUserInfo(uid),
msg: new MsgApi(this.ctx).unreadTotal(uid)
}
);
let avatar = helpers.image(_.get(result, 'profile.data.head_ico', ''), 100, 100) || defaultAvatar;
let msgCount = _.get(result, 'msg.data.total', 0);
return Promise.resolve({avatar: avatar, msg: msgCount});
}
// 首页顶部数量
async numbers(uid, udid) {
let result = {};
let numbers = await Promise.props({
pending: new IndexApi(this.ctx).pendingOrderCount(uid), // 待处理订单
unread: new IndexApi(this.ctx).unreadMessageCount(uid, udid), // 未读消息
needComment: new IndexApi(this.ctx).needCommentCount(uid) // 待评论商品
});
result[numbersKey.pending] = _.get(numbers, 'pending.data.count', 0);
result[numbersKey.unread] = _.get(numbers, 'unread.data.inbox_total', 0);
result[numbersKey.needComment] = _.get(numbers, 'needComment.data', 0);
return Promise.resolve(result);
}
// 个人中心首页同步数据
async indexNew(uid, udid, channel, isStudent) {
let indexData = await Promise.props({
header: headerModel.requestHeaderData(channel),
recentOrder: this._recentOrder(uid),
footerBanner: this._footerBanner(),
reason: this._cancelReason()
});
return Object.assign(
{
content: {
content: {
messages: [
{href: helpers.urlFormat('/home/orders'), name: '待处理订单', id: numbersKey.pending, count: 0},
{href: helpers.urlFormat('/home/message'), name: '未读消息', id: numbersKey.unread, count: 0},
{href: helpers.urlFormat('/home/comment'), name: '待评论商品',
id: numbersKey.needComment, count: 0}
],
certifiedName: +isStudent ? '学生身份已验证' : '身份验证',
certifiedUrl: helpers.urlFormat('/product/students/'),
latestOrders: Object.assign(indexData.recentOrder, {cancelReason: indexData.reason})
},
banner: indexData.footerBanner
}
},
{
header: indexData.header
}
);
}
index(uid, udid, channel, isStudent) {
let that = this;
... ...
... ... @@ -50,9 +50,27 @@ const invoiceController = require(`${cRoot}/invoice`);
const meGiftController = require(`${cRoot}/me-gift`);
const checkLogin = (res, req, next) => {
if (req.user.uid) {
return next();
} else {
if (res.xhr) {
res.json({code: 401, message: '未登录!'});
} else {
res.redirect('/login.html');
}
}
};
// 首页
router.get(['/index', '/'], tabsMiddleware.getCommonHeader, indexController.index);
router.get(['/index', '/'], tabsMiddleware.getCommonHeaderNew, indexController.index);
router.get('/index/brands', checkLogin, indexController.brands);
router.get('/index/newArrive', checkLogin, indexController.newArrive);
router.get('/index/recommend', checkLogin, indexController.recommend);
router.get('/index/newsAvatar', checkLogin, indexController.newsAvatar);
router.get('/index/numbers', checkLogin, indexController.numbers);
// router.get(['/index', '/'], tabsMiddleware.getCommonHeader, indexController.index);
// 查看二维码
router.get('/QRcode', tabsMiddleware.getCommonHeader, personalController.QRcode);
... ...
... ... @@ -10,7 +10,7 @@
消息提示:
{{# messages}}
<a href="{{href}}">{{name}}</a>
<b>({{count}})</b>
<b id="{{id}}">({{count}})</b>
{{/ messages}}
{{#unless @root.pc.user.removeStudentIdentification}}
... ... @@ -36,88 +36,86 @@
{{> home/orders/order-block}}
</div>
{{/ latestOrders}}
{{# favBrand}}
<div class="brands block">
<h2 class="title">
<a class="more-orders more" href="{{more}}">
更多品牌
</a>
</h2>
<ul class="clearfix">
{{# brands}}
<li>
<a href="{{href}}">
<img class="brand-logo" src="{{logo}}">
<span class="brand-name">{{name}}</span>
</a>
</li>
{{/ brands}}
</ul>
<div class="brands block" id="home-brands-box">
</div>
{{/ favBrand}}
{{#if newArrival}}
<div class="new-arrival block">
<h2 class="title">
<p class="na-pager-wrap">
<span class="na-pager pre no-visible">
<i class="iconfont">&#xe618;</i>
</span>
<span class="na-pager next">
<i class="iconfont">&#xe619;</i>
</span>
</p>
</h2>
<ul class="clearfix">
{{# newArrival}}
<li>
<a href="{{href}}">
<img class="thumb" src="{{thumb}}">
<p class="name">{{name}}</p>
<span class="price">¥{{price}}</span>
</a>
</li>
{{/ newArrival}}
</ul>
<div class="new-arrival block" id="home-new-box">
</div>
{{/if}}
{{/ content}}
</div>
<!--recommend-for-you-->
{{#if recommend}}
<div class="recommend block">
<h2 class="title">
<p class="na-pager-wrap">
<span class="rc-pager pre no-visible">
<i class="iconfont">&#xe618;</i>
</span>
<span class="rc-pager next">
<i class="iconfont">&#xe619;</i>
</span>
</p>
</h2>
<ul class="clearfix">
{{# recommend}}
<li>
<a href="{{href}}" data-id='{{productId}}' target="_blank">
<img class="thumb" src="{{thumb}}">
<p class="name">{{name}}</p>
<span class="price">¥{{price}}</span>
</a>
</li>
{{/ recommend}}
</ul>
<div class="recommend block" id="home-recommend-box">
</div>
{{/if}}
<!--recommend-for-you-->
<div class="ho-btm">
{{{banner}}}
{{> help-us}}
</div>
{{/ me}}
<script type="text/html" id="home-brands-tpl">
<h2 class="title">
<a class="more-orders more" href="\{{more}}">
更多品牌
</a>
</h2>
<ul class="clearfix">
\{{# brands}}
<li>
<a href="\{{href}}">
<img class="brand-logo" src="\{{logo}}">
<span class="brand-name">\{{name}}</span>
</a>
</li>
\{{/ brands}}
</ul>
</script>
<script type="text/html" id="home-new-tpl">
\{{#if newArrive}}
<h2 class="title">
<p class="na-pager-wrap">
<span class="na-pager pre no-visible">
<i class="iconfont">&#xe618;</i>
</span>
<span class="na-pager next">
<i class="iconfont">&#xe619;</i>
</span>
</p>
</h2>
<ul class="clearfix">
\{{# newArrive}}
<li>
<a href="\{{href}}">
<img class="thumb" src="\{{thumb}}">
<p class="name">\{{name}}</p>
<span class="price">¥\{{price}}</span>
</a>
</li>
\{{/ newArrive}}
</ul>
\{{/if}}
</script>
<script type="text/html" id="home-recommend-tpl">
\{{#if recommend}}
<h2 class="title">
<p class="na-pager-wrap">
<span class="rc-pager pre no-visible">
<i class="iconfont">&#xe618;</i>
</span>
<span class="rc-pager next">
<i class="iconfont">&#xe619;</i>
</span>
</p>
</h2>
<ul class="clearfix">
\{{# recommend}}
<li>
<a href="\{{href}}" data-id='\{{productId}}' target="_blank">
<img class="thumb" src="\{{thumb}}">
<p class="name">\{{name}}</p>
<span class="price">¥\{{price}}</span>
</a>
</li>
\{{/ recommend}}
</ul>
\{{/if}}
</script>
</div>
... ...
... ... @@ -2,9 +2,7 @@
<p class="title ucenter"></p>
<div class="user-thumb">
<div class="thumb-bg">
{{#if userThumb}}
<img id="user-thumb" src="{{image2 userThumb w=100 h=100}}">
{{/if}}
<img id="user-thumb">
</div>
</div>
{{# homeNav}}
... ... @@ -18,7 +16,7 @@
<li class="row{{#if @first}} first{{/if}}{{#if active}} active{{/if}}">
<a href="{{href}}" target="{{#if isBlank}}_blank{{/if}}" >{{name}}</a>
{{#if count}}
<span class="new-count">{{count}}</span>
<span class="new-count hide" id="new-count">{{count}}</span>
{{/if}}
</li>
{{/each}}
... ...
... ... @@ -4,12 +4,14 @@
* @date: 2016/2/17
*/
var $ = require('yoho-jquery');
var $ = require('yoho-jquery'),
handlebars = require('yoho-handlebars');
var yas = require('../common/data-yas');
var RECID = (new Date().getTime() + '_PC_YOHOBUY_' +
Math.floor(Math.random() * 1000000 + 1000000) +
'_' + Math.floor(Math.random() * 1000000 + 1000000));
require('./orders/order-block');
require('../common');
... ... @@ -76,6 +78,13 @@ function pageChange(self, $ul, page, itemWith, curPage, num) {
rcCurPage = 1,
PRDID = [];
var $brandsBox = $('#home-brands-box'),
$newBox = $('#home-new-box'),
$recommendBox = $('#home-recommend-box'),
$brandsTpl = $('#home-brands-tpl').html(),
$newTpl = $('#home-new-tpl').html(),
$recommendTpl = $('#home-recommend-tpl').html();
$naUl.width($naUl.width() * naPage);
$rcUl.width($rcUl.width() * rcPage);
... ... @@ -167,4 +176,34 @@ function pageChange(self, $ul, page, itemWith, curPage, num) {
// 为您优选埋点 end
// 我的消息、我的头像
$.getJSON('//www.yohobuy.com/home/index/newsAvatar', function(data) {
$('#user-thumb').attr('src', data.avatar);
if (+data.msg > 0) {
$('#new-count').html(data.msg).removeClass('hide');
}
});
// 待处理订单,未读消息,待分享商品数量
$.getJSON('//www.yohobuy.com/home/index/numbers', function(numbers) {
$.each(numbers, function(key, val) {
$('#' + key).html(val);
});
});
// 喜欢的品牌
$.getJSON('//www.yohobuy.com/home/index/brands', function(brands) {
$brandsBox.html(handlebars.compile($brandsTpl)(brands));
});
// 新品上架
$.getJSON('//www.yohobuy.com/home/index/newArrive', function(products) {
$newBox.html(handlebars.compile($newTpl)(products));
});
// 猜你喜欢
$.getJSON('//www.yohobuy.com/home/index/recommend', function(rec) {
$recommendBox.html(handlebars.compile($recommendTpl)(rec));
});
}());
... ...