Authored by htoooth

merge recommned

... ... @@ -233,6 +233,22 @@ const createConsult = (req, res, next) => {
}
};
const recommend = (req, res, next) => {
let skn = req.query.skn || '';
let pageSize = req.query.size || 5;
let pageNum = req.query.num || 1;
if (!skn) {
return res.json({
code: 400,
message: '服务器错误'
});
}
service.recommendAsync(skn, pageNum, pageSize)
.then(result => res.json(result))
.catch(next);
};
module.exports = {
showMain,
... ... @@ -241,7 +257,8 @@ module.exports = {
indexConsult,
createConsult,
productHeader: detailHeader,
detailReturn
detailReturn,
recommend
};
... ...
... ... @@ -104,6 +104,20 @@ const getLimitedProductStatusAsync = (code, uid, skn) => {
return api.get('', params, config.apiCache);
};
/**
*
* @param skn product_skn
* @param sid shop_id
*/
const getShopRecommendAsync = (skn, page, limit) => {
return api.get('', {
method: 'web.product.shopRecommend',
product_skn: skn,
page: page,
limit: limit
});
};
module.exports = {
getProductBannerAsync,
sizeInfoAsync,
... ... @@ -113,5 +127,6 @@ module.exports = {
getProductAsync,
getPromotionAsync,
isSupportReturnedSale,
getLimitedProductStatusAsync
getLimitedProductStatusAsync,
getShopRecommendAsync
};
... ...
... ... @@ -1234,7 +1234,6 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => {
let notForSale = propOrigin('attribute') === 2; // 非卖品
let virtualGoods = propOrigin('attribute') === 3; // 虚拟商品
if (virtualGoods) {
result.virtualGoods = virtualGoods;
... ... @@ -1450,6 +1449,57 @@ const showMainAsync = (data) => {
})();
};
const recommendAsync = (skn, page, limit) => {
return co(function * () {
let recommendData = yield productAPI.getShopRecommendAsync(skn, page, limit);
if (_.get(recommendData, 'code', 400) !== 200) {
return {
code: 400,
message: '服务器错误!'
};
}
const formatPrice = p => ${p}`;
const productUrl = (pid, gid, cn) => helpers.urlFormat(`/product/pro_${pid}_${gid}/${cn}.html`, null, 'item');
const productImageUrl = Fn.pipe(Fn.prop('default_images'), _.partial(helpers.image, _, 150, 200, 2, 70));
let products = _.get(recommendData, 'data.product_list', []).map((rp) => {
let marketPrice = rp.sales_price;
let salePrice = rp.market_price;
let defaultGoods = _.find(rp.goods_list, {is_default: 'Y'});
// 无默认商品取商品列表第一个
if (!defaultGoods) {
defaultGoods = rp.goods_list[0];
}
return {
market_price: marketPrice === salePrice ? '' : formatPrice(helpers.round(marketPrice, 2)),
price: formatPrice(helpers.round(salePrice, 2)),
product_name: rp.product_name,
url: productUrl(rp.product_id, defaultGoods.goods_id, rp.cn_alphabet),
pic_url: productImageUrl(rp)
};
});
return {
code: 200,
data: {
pager: {
total: _.get(recommendData, 'page_total', 0),
size: _.get(recommendData, 'page_size', 5),
num: _.get(recommendData, 'page', 1)
},
products: products,
total: _.get(recommendData, 'total', 0)
}
};
})();
};
module.exports = {
getShareOrderListAsync: commentService.getShareOrderListAsync, // 获取评论列表
indexConsultAsync: consultService.indexAsync, // 获取咨询列表
... ... @@ -1458,5 +1508,6 @@ module.exports = {
indexHotAreaAsync: hotAreaService.indexAsync, // 获取某一个商品的热区数据
saveRecentGoodInCookies, // 保存最近的商品
getDetailHeader,
saleReturn
saleReturn,
recommendAsync
};
... ...
... ... @@ -64,6 +64,7 @@ router.post('/index/favoriteBrand', favorite.changeFavoriteBrand);// 收è—å“ç‰
router.post('/item/togglecollect', favorite.collectProduct); // 收藏商品
router.get('/detail/header', detail.productHeader); // 价格数据重新获取接口
router.get('/detail/return', detail.detailReturn);// 特殊商品退换货
router.get('/detail/recommend', detail.recommend);// 推荐商品
router.get('/index/isfav', favorite.isFavoriteBrand);// 品牌收藏状态
router.get('/detail/coupon', auth, coupon.acquire); // 获得优惠券
... ...
... ... @@ -233,6 +233,16 @@
</div>
{{# consultComment}}
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchComment();
fetchReturn();
loadRecommend();
</script>
</textarea>
</div>
<div class="consult-comment info-block">
<p class="block-title">
... ... @@ -303,16 +313,6 @@
</p>
</div>
</div>
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchComment();
fetchReturn();
</script>
</textarea>
</div>
</div>
{{/ consultComment}}
... ... @@ -354,23 +354,36 @@
<div class="service"></div>
{{#unless @root.pc.product.removeRecentView}}
{{#if latestWalk}}
<div class="info-block latest-walk">
<input id="latest-walk-count" type="hidden" value="{{latestWalk}}">
<p class="block-title">
<span class="title cur">最近浏览 RECENT REVIEW</span>
</p>
<div id="latest-walk-goods" class="goods clearfix"></div>
{{> product/latest-walk-tpl}}
<div class="individual-comment info-block">
<p class="block-title">
<span class="title cur">店铺推荐 SHOP RECOMMENDED</span>
<span class="sep">|</span>
<span class="title">最近浏览 RECENT REVIEW</span>
</p>
{{#if latestWalk}}
<div class="latest-walk">
<input id="latest-walk-count" type="hidden" value="{{latestWalk}}">
<div id="latest-walk-goods" class="goods clearfix"></div>
{{> product/latest-walk-tpl}}
</div>
{{/if}}
{{/if}}
<div id="recommend-shop" class="hide">
<div class="recommend-content clearfix">
<div class="recommend-slider">
<ul class=" img-list" id="recommend-content"></ul>
<div class="img-brand-switch">
<a class="prev iconfont" href="javascript:;">&#xe609;</a>
<a class="next iconfont" href="javascript:;">&#xe608;</a>
</div>
</div>
</div>
</div>
</div>
{{/unless}}
</div>
</div>
{{/ detail}}
<script id="consults-tpl" type="text/html">
</script>
</div>
{{# statGoodsInfo}}
... ...
... ... @@ -17,11 +17,16 @@ module.exports = {
cookieDomain: '.yohobuy.com',
domains: {
favApi: 'http://192.168.102.31:8092/brower',
api: 'http://api-test1.yohops.com:9999/',
service: 'http://service-test1.yohops.com:9999/',
// api: 'http://api-test1.yohops.com:9999/',
// service: 'http://service-test1.yohops.com:9999/',
// api: 'http://api.yoho.cn/',
// service: 'http://service.yoho.cn/',
api: 'http://dev-api.yohops.com:9999/',
service: 'http://dev-service.yohops.com:9999/',
search: 'http://192.168.102.216:8080/yohosearch/'
},
subDomains: {
... ... @@ -67,7 +72,7 @@ module.exports = {
port: '4444' // influxdb port
},
console: {
level: 'error',
level: 'info',
colorize: 'all',
prettyPrint: true
}
... ... @@ -116,10 +121,10 @@ if (isProduction) {
master: ['memcache1.yohoops.org:12111', 'memcache2.yohoops.org:12111', 'memcache3.yohoops.org:12111'],
slave: ['memcache1.yohoops.org:12112', 'memcache2.yohoops.org:12112', 'memcache3.yohoops.org:12112'],
session: ['memcache1.yohoops.org:12111', 'memcache2.yohoops.org:12111', 'memcache3.yohoops.org:12111'],
poolSize: 100,
poolSize: 25,
reconnect: 5000,
timeout: 300,
retries: 0,
retries: 1,
retry: 3000
},
useOneapm: true,
... ...
... ... @@ -12,8 +12,4 @@
</div>
\{{/ latestWalk}}
</script>
<div class="lazy-load-object">
<textarea class="latest-walk-datalazyload" style="visibility: hidden;">
<script> fetchLatestWalk(); </script>
</textarea>
</div>
... ...
... ... @@ -7,5 +7,11 @@
</div>
{{> product/latest-walk-tpl}}
<div class="lazy-load-object">
<textarea class="latest-walk-datalazyload" style="visibility: hidden;">
<script> fetchLatestWalk(); </script>
</textarea>
</div>
{{/if}}
{{/unless}}
... ...
{{# products}}
<li class="img-item">
<div class="good">
<a href="{{url}}" target="_blank">
<img class="lazy" src="{{pic_url}}"/>
</a>
<a class="name" href="{{url}}" target="_blank">{{product_name}}</a>
<p class="price">
<span class="market-price">{{market_price}}</span>
<span class="sale-price">{{price}}</span>
</p>
</div>
</li>
{{/ products}}
... ...
... ... @@ -49,6 +49,9 @@ function isEmpty(el) {
return !$.trim(el.html());
}
require('../plugins/slider');
require('../common/center-slider');
bindEvent.add(function() {
var $imgShow = $('#img-show'),
$thumbs = $('#thumbs > .thumb-wrap');
... ... @@ -789,9 +792,6 @@ function fetchComment() {
return;
}
// 更新总数显示
// $commentNum.text(res[0].total);
if (filter && filter.length && !cNumReady) {
cNumReady = true;
$(filter).each(function(idx, fit) {
... ... @@ -815,13 +815,6 @@ function fetchComment() {
});
}
// 购买有图评价
/* function loadPicComments() {
loadComments(commentType.PIC).then(function(data){
});
}*/
// 顾客咨询
function loadConsults() {
if (loadingConsults) {
... ... @@ -1019,6 +1012,78 @@ $('.comments').on('click', '.img-preview [data-role="preview-right"]', function(
$img.css('transform', 'rotate(' + rotate + 'deg)');
});
// 店铺推荐
function loadRecommend() {
$.ajax({
type: 'GET',
url: '/product/detail/recommend',
data: {
skn: skn,
size: 20,
num: 1
}
}).then(function(data) {
var pro = data.data.products;
var recommendTpl = require('hbs/product/recommend.hbs');
var html = recommendTpl(data.data);
if (data.code === 200) {
if (pro.length === 0) {
$('.individual-comment').find('.block-title .title:first-child').addClass('hide');
$('.individual-comment').find('.block-title').find('.title')
.addClass('cur').prev('.sep').addClass('hide');
$('#recommend-shop').detach();
}
$('#recommend-shop').removeClass('hide');
$('#recommend-content').append(html);
$('.recommend-slider').slider2({
shownum: 5,
isCircle: false
});
} else {
$('.individual-comment').find('.block-title .title:first-child').addClass('hide');
$('.individual-comment').find('.block-title').find('.title').addClass('cur').prev('.sep').addClass('hide');
$('#recommend-shop').detach();
}
});
}
window.loadRecommend = loadRecommend;
// 推荐和浏览切换
$('.individual-comment').on('click', '.title', function() {
var $this = $(this),
index = $this.index();
var $latestWalk = $('.latest-walk'),
$recommendComment = $('#recommend-shop');
if ($this.hasClass('cur')) {
return;
}
$this.addClass('cur');
$this.siblings('.cur').removeClass('cur');
if (index === 0) {
// 店铺推荐
$recommendComment.slideDown(SLIDETIME);
$latestWalk.slideUp(SLIDETIME);
} else {
// 最近游览
fetchLatestWalk(); // eslint-disable-line
$recommendComment.slideUp(SLIDETIME);
$latestWalk.slideDown(SLIDETIME);
}
});
$('.recommend-content').find('.iconfont').mouseenter(function() {
$(this).addClass('focus');
}).mouseleave(function() {
$(this).removeClass('focus');
});
// 特殊商品退换货
function fetchReturn() {
return $.ajax({
... ...
... ... @@ -18,6 +18,10 @@ function fetchLatestWalk() {
return;
}
if ($('#latest-walk-goods').html()) {
return;
}
tpl = Handlebars.compile($('#latest-walk-tpl').html());
$.ajax({
... ... @@ -51,6 +55,7 @@ function fetchLatestWalk() {
}
if (latestWalk.length > 0) {
$('#latest-walk-goods').html(tpl({
latestWalk: latestWalk
}));
... ...
// /**
// * 最近浏览取接口渲染模板
// * @author: xuhui<xuhui.ge@yoho.cn>
// 8 @date: 2016/11/09
// */
//
// var $ = require('yoho-jquery');
// var Handlebars = require('yoho-handlebars');
// var lazyLoad = require('yoho-jquery-lazyload');
// var dataLazyLoad = require('../../plugins/lazy-load')(document);
//
//
// function shopRecommend() {
// var tpl;
//
// tpl = Handlebars.compile($('#recommend-shop').html());
//
// $.ajax({
// url: 'product/detail/recommend',
//
// success: function(data) {
// var recommendShop = [],
// res, i, cur;
//
// if (data.code === 200) {
// res = data.data;
//
// for (i = 0; i < res.length; i++) {
// cur = res[i];
//
// recommendShop.push({
// href: cur.url,
// img: cur.pic_url,
// name: cur.product_name,
// salePrice: cur.price
// });
// }
//
// if (recommendShop.length > 0) {
// $('#recommend-shop').html(tpl({
// recommendShop: recommendShop
// }));
//
// lazyLoad($('#recommend-shop .lazy'));
// }
// }
// }
// });
// }
//
// window.shopRecommend = shopRecommend;
//
// // 数据懒加载
// dataLazyLoad.init({cls: '.latest-walk-datalazyload', threshold: 700});
... ...
... ... @@ -1227,6 +1227,7 @@
.not-support-saleReturned-service {
$service: product/limit.png;
width: width($service);
height: height($service);
margin: 45px auto;
... ... @@ -1235,6 +1236,7 @@
.latest-walk {
overflow: inherit;
border-top: none;
.goods {
width: 1010px;
... ... @@ -1366,6 +1368,109 @@
}
}
}
.recommend-content {
position: relative;
height: 300px;
overflow: hidden;
.recommend-slider {
margin: 0 80px;
box-sizing: border-box;
width: 990px;
height: 300px;
overflow: hidden;
}
ul {
height: 100%;
}
li {
float: left;
width: 200px;
height: 300px;
overflow: hidden;
}
.img-brand-switch {
display: block;
a {
position: absolute;
top: 50%;
margin-top: -40px;
font-size: 24px;
color: #fff;
width: 40px;
height: 32px;
padding-top: 8px;
text-align: center;
background-color: #b0b0b0;
&.focus {
background-color: #444;
}
&.prev {
left: 0;
}
&.next {
right: 0;
}
}
}
.good {
float: left;
width: 180px;
margin-right: 22px;
a {
cursor: pointer;
& > div {
background-color: #f4f7f6;
}
}
img {
display: block;
width: 180px;
height: 240px;
}
.name {
display: block;
max-width: 150px;
height: 18px;
line-height: 16px;
margin: 5px 0;
color: #222;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.price {
color: #222;
font-weight: 700;
margin-top: 5px;
}
.market-price {
color: #999;
margin-right: 5px;
text-decoration: line-through;
}
.sale-price {
color: #000;
font-weight: 700;
}
}
}
}
.coupon-big {
... ...