diff --git a/apps/common/controllers/suggestFeedBack.js b/apps/common/controllers/suggestFeedBack.js index 8a5bf32..8c85602 100644 --- a/apps/common/controllers/suggestFeedBack.js +++ b/apps/common/controllers/suggestFeedBack.js @@ -11,7 +11,7 @@ const suggestFeedBackModel = require('../models/suggestFeedBack-service'); const getFeedBack = (req, res, next) => { - suggestFeedBackModel.suggestFeedBack().then((result) => { + suggestFeedBackModel.suggestFeedBack(req.user.uid).then((result) => { res.jsonp(result); }).catch(next); }; diff --git a/apps/common/models/suggestFeedBack-api.js b/apps/common/models/suggestFeedBack-api.js index daa5de4..1ce8224 100644 --- a/apps/common/models/suggestFeedBack-api.js +++ b/apps/common/models/suggestFeedBack-api.js @@ -14,9 +14,9 @@ const URL_ACTIVITY_QUESTION = '/activity/question/'; * @param uid * @return string */ -const feedBackApi = () => { +const feedBackApi = (uid) => { - return service.get(URL_ACTIVITY_QUESTION + 'questionList', {}); + return service.get(URL_ACTIVITY_QUESTION + 'questionList', {uid: uid}); }; module.exports = { diff --git a/apps/common/models/suggestFeedBack-service.js b/apps/common/models/suggestFeedBack-service.js index 823f967..edcb54d 100644 --- a/apps/common/models/suggestFeedBack-service.js +++ b/apps/common/models/suggestFeedBack-service.js @@ -9,9 +9,9 @@ const api = require('./suggestFeedBack-api'); const helpers = global.yoho.helpers; const _ = require('lodash'); -const suggestFeedBack = () => { +const suggestFeedBack = (uid) => { - return api.feedBackApi().then((result) => { + return api.feedBackApi(uid).then((result) => { let suggestData = []; if (result && result.code === 200 && _.get(result, 'data.rows')) { diff --git a/apps/product/controllers/search.js b/apps/product/controllers/search.js index 4d26461..9928713 100644 --- a/apps/product/controllers/search.js +++ b/apps/product/controllers/search.js @@ -210,28 +210,29 @@ const keyId = (req, res, next) => { let params = req.query; let id = req.params.id; - return search.getSearchKeywordDataById(id, params, req.yoho.channel).then(result => { + return search.getSearchKeywordDataById(id, Object.assign({stocknumber: -1}, params), + req.yoho.channel).then(result => { - if (!result) { - return next(); - } + if (!result) { + return next(); + } - let query = result.queryKey; + let query = result.queryKey; - Object.assign(result, { - pageNoFollow: true, - title: `${query}价格_图片_品牌_怎么样-YOHO!BUY有货`, - keywords: `${query},${query}价格,${query}图片,${query}怎么样,${query}品牌,YOHO!BUY有货`, - description: `YOHO!BUY有货网yohobuy.com是国内专业的${query}网上潮流购物商城,为您找到${_.get(result, + Object.assign(result, { + pageNoFollow: true, + title: `${query}价格_图片_品牌_怎么样-YOHO!BUY有货`, + keywords: `${query},${query}价格,${query}图片,${query}怎么样,${query}品牌,YOHO!BUY有货`, + description: `YOHO!BUY有货网yohobuy.com是国内专业的${query}网上潮流购物商城,为您找到${_.get(result, 'search.totalCount', 0)}条${query}、产品的详细参数,实时报价,价格行情,图片、评价、品牌等信息。买${query},就上YOHO!BUY有货` - }); + }); - if (!_.get(result, 'search.goods') || !_.get(result, 'search.goods').length) { - _.set(result, 'search.keyWord', query); - return res.render('search/no-result', result); - } - res.render('search/index', result); - }).catch(next); + if (!_.get(result, 'search.goods') || !_.get(result, 'search.goods').length) { + _.set(result, 'search.keyWord', query); + return res.render('search/no-result', result); + } + res.render('search/index', result); + }).catch(next); }; module.exports = { diff --git a/apps/product/models/detail-hotarea-service.js b/apps/product/models/detail-hotarea-service.js index b2c6d68..0a31311 100644 --- a/apps/product/models/detail-hotarea-service.js +++ b/apps/product/models/detail-hotarea-service.js @@ -56,7 +56,7 @@ const indexAsync = pid => { marketPrice: cur.product.productPriceBo.formatMarketPrice, productName: cur.product.productName, href: helpers.getUrlBySkc( - _.get(goods, 'goodsImagesList[0].productSkn', '')) + _.get(cur.product, 'productPriceBo.productSkn', '')) }; acc.push(point); diff --git a/apps/product/models/detail-product-api.js b/apps/product/models/detail-product-api.js index f343f75..0971838 100644 --- a/apps/product/models/detail-product-api.js +++ b/apps/product/models/detail-product-api.js @@ -6,6 +6,7 @@ const api = global.yoho.API; const config = global.yoho.config; +const redis = global.yoho.redis; /** * 商品的 banner @@ -131,8 +132,8 @@ const getShopRecommendAsync = (skn, page, limit) => { return api.get('', { method: 'web.product.shopRecommend', product_skn: skn, - page: page, - limit: limit + page: page || 1, + limit: limit || 20 }); }; @@ -146,6 +147,24 @@ const getBundleAsync = (skn) => { }); }; +/** + * 找相似 + */ +const getLikeAsync = (skn, limit) => { + return api.get('', { + method: 'app.search.findLike', + limit: limit || 10, + product_skn: skn + }); +}; + +// 根据small_sort从redis获取分类下的关键词 +const getRecommendKeywords = (smallSort) => { + return redis.all([['get', `golobal:yoho:seo:keywords:sortId:${smallSort}`]]).then(res => { + return res[0]; + }); +}; + module.exports = { getProductBannerAsync, sizeInfoAsync, @@ -156,5 +175,7 @@ module.exports = { isSupportReturnedSale, getLimitedProductStatusAsync, getShopRecommendAsync, - getBundleAsync + getBundleAsync, + getLikeAsync, + getRecommendKeywords }; diff --git a/apps/product/models/detail-service.js b/apps/product/models/detail-service.js index e32062a..176c3e4 100644 --- a/apps/product/models/detail-service.js +++ b/apps/product/models/detail-service.js @@ -36,6 +36,7 @@ const BLANK_STR = ' '; const BUNDLE_PRODUCE = 2; // 量贩 const BUNDLE_PACKAGE = 1; // 套餐 const tdk = require('../../../utils/getTDK'); +const Helpers = global.yoho.helpers; const _getProductAdditionInfoAsync = (data) => { return co(function * () { @@ -1010,6 +1011,19 @@ const _getIntroInfo = (productSkn, maxSortId, additionalData)=> { return result; }; +// 返回6条推荐关键词页面 +const getKeywordsInfo = (keywords) => { + let res = []; + + _.forEach(_.slice(_.shuffle(keywords), 0, 12), val => { + res.push({ + url: Helpers.urlFormat(`/chanpin/${val.id}.html`), + keyword: val.keyword + }); + }); + return res; +}; + /** * 获取seo信息 * @@ -1104,6 +1118,9 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => { return result; } + // sku商品信息,尺寸信息 + let skuData = _getSkuDataByProductBaseInfo(origin); + result.name = propOrigin('product_name'); result.skn = propOrigin('product_skn'); result.productId = propOrigin('product_id'); @@ -1146,6 +1163,17 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => { requestApi.bundle = productAPI.getBundleAsync(result.skn); // 量贩 } + // 找相似 + if (skuData.totalStorageNum === 0) { + requestApi.alike = productAPI.getLikeAsync(result.skn); + } + + // 相关推荐词 + requestApi.recommendKeywords = productAPI.getRecommendKeywords(result.smallSortId); + + // 店铺推荐直出(seo需要) + requestApi.shopRecommend = productAPI.getShopRecommendAsync(result.skn); + let requestData = yield Promise.props(requestApi); let additionalData = requestData.addition; @@ -1154,6 +1182,20 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => { let coupon = requestData.coupon; let limitedInfo = requestData.limited; let bundle = requestData.bundle; + let recommendKeywords = requestData.recommendKeywords ? JSON.parse(requestData.recommendKeywords) : []; + + // 处理相似商品 + result.alike = _.map(_.get(requestData, 'alike.data.product_list', ''), val =>{ + return Object.assign({url: Helpers.getUrlBySkc(val.product_skn)}, val); + }); + + // 推荐关键词页面 + result.recommendKeywords = getKeywordsInfo(recommendKeywords); + + // 处理店铺推荐 + result.shopRecommend = _.map(_.get(requestData, 'shopRecommend.data.product_list', ''), val =>{ + return Object.assign({url: Helpers.getUrlBySkc(val.product_skn)}, val); + }); // 商品标签 result.tags = _getTagsDataByProductInfo(origin); @@ -1241,9 +1283,6 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => { result.presale = 'Y'; } - // sku商品信息,尺寸信息 - let skuData = _getSkuDataByProductBaseInfo(origin); - result.img = skuData.defaultImage; result.colors = skuData.skuGoods; let totalStorageNum = skuData.totalStorageNum; @@ -1723,7 +1762,6 @@ const getPackage = co(function * (skn) { return resData; }); - module.exports = { getShareOrderListAsync: commentService.getShareOrderListAsync, // 获取评论列表 indexConsultAsync: consultService.indexAsync, // 获取咨询列表 diff --git a/apps/product/views/action/product/detail.hbs b/apps/product/views/action/product/detail.hbs index 18e844c..6810156 100644 --- a/apps/product/views/action/product/detail.hbs +++ b/apps/product/views/action/product/detail.hbs @@ -23,6 +23,8 @@ <div id="package" class="package-box clearfix hide"></div> + {{> product/alike}} + <div class="total-content"> <div class="other-infos"> {{> product/description}} @@ -39,6 +41,8 @@ {{> product/after-service}} + {{> product/recommend-keywords}} + {{> product/recommend-receiveview}} </div> diff --git a/apps/product/views/partial/product/alike.hbs b/apps/product/views/partial/product/alike.hbs new file mode 100644 index 0000000..40c89a4 --- /dev/null +++ b/apps/product/views/partial/product/alike.hbs @@ -0,0 +1,40 @@ +{{#if goodsInfo.alike}} + <div class="bottom-tab alike-title"> + <p> + <span class="bottom-title bottom-cur">相似商品</span> + <span class="bottom-title change">换一批 + <span class="iconfont change-icon"></span> + </span> + </p> + </div> + + <div class="individual-comment info-block info-bottom alike"> + <div> + <div class="recommend-content clearfix"> + <div class="recommend-slider-alike"> + <ul class=" img-list"> + {{# goodsInfo.alike}} + <li class="img-item"> + <span class="hide goods-id">{{goods_id}}</span> + <div class="good"> + <a href="{{url}}" target="_blank"> + <img class="lazy" src="{{image2 default_images w=280 h=382}}"/> + </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">¥{{sales_price}}</span> + </p> + </div> + </li> + {{/goodsInfo.alike}} + </ul> + <div class="img-brand-switch"> + <a class="prev iconfont" href="javascript:;"></a> + <a class="next iconfont" href="javascript:;"></a> + </div> + </div> + </div> + </div> + </div> +{{/if}} \ No newline at end of file diff --git a/apps/product/views/partial/product/recommend-keywords.hbs b/apps/product/views/partial/product/recommend-keywords.hbs new file mode 100644 index 0000000..1520b4d --- /dev/null +++ b/apps/product/views/partial/product/recommend-keywords.hbs @@ -0,0 +1,10 @@ +{{#if goodsInfo.recommendKeywords}} + <div class="recommend-keywords"> + <h3>相关推荐</h3> + <p> + {{# goodsInfo.recommendKeywords}} + <a href="{{url}}" title="{{keyword}}" target="_blank">{{keyword}}</a> + {{/ goodsInfo.recommendKeywords}} + </p> + </div> +{{/if}} diff --git a/apps/product/views/partial/product/recommend-receiveview.hbs b/apps/product/views/partial/product/recommend-receiveview.hbs index 9b470b3..cd5ac55 100644 --- a/apps/product/views/partial/product/recommend-receiveview.hbs +++ b/apps/product/views/partial/product/recommend-receiveview.hbs @@ -25,17 +25,34 @@ {{> product/latest-walk-tpl}} </div> {{/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:;"></a> - <a class="next iconfont" href="javascript:;"></a> + {{#if goodsInfo.shopRecommend}} + <div id="recommend-shop"> + <div class="recommend-content clearfix"> + <div class="recommend-slider"> + <ul class=" img-list" id="recommend-content"> + {{# goodsInfo.shopRecommend}} + <li class="img-item"> + <span class="hide goods-id">{{goods_id}}</span> + <div class="good"> + <a href="{{url}}" target="_blank"> + <img class="lazy" src="{{image2 default_images w=280 h=382}}"/> + </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">¥{{sales_price}}</span> + </p> + </div> + </li> + {{/ goodsInfo.shopRecommend}} + </ul> + <div class="img-brand-switch"> + <a class="prev iconfont" href="javascript:;"></a> + <a class="next iconfont" href="javascript:;"></a> + </div> </div> </div> </div> - </div> + {{/if}} </div> {{/unless}} diff --git a/doraemon/middleware/redis.js b/doraemon/middleware/redis.js index b015541..4f72550 100644 --- a/doraemon/middleware/redis.js +++ b/doraemon/middleware/redis.js @@ -3,6 +3,8 @@ const _ = require('lodash'); const redis = require('redis'); const bluebird = require('bluebird'); const config = require('../../config/common'); +const logger = global.yoho.logger; +const timeout = 200; // redis 操作超时时间 let client; try { @@ -20,9 +22,14 @@ try { } } - return client.multi.call(client, args).execAsync(); + return client.multi.call(client, args).execAsync().timeout(timeout).catch(()=>{ + logger.err('redis exe time out'); + return false; + }); }; + + client.on('error', function() { global.yoho.redis = ''; }); diff --git a/doraemon/views/partial/footer.hbs b/doraemon/views/partial/footer.hbs index 4f81c1c..08d3287 100644 --- a/doraemon/views/partial/footer.hbs +++ b/doraemon/views/partial/footer.hbs @@ -293,6 +293,10 @@ <a href="//www.yohobuy.com/privacy.html" rel="nofollow">隐私条款</a> <span>|</span> <a href="//www.yohobuy.com/link.html">友情链接</a> + <span>|</span> + <a class="police" target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=32010502010132"> + 苏公网安备 32010502010132号 + </a> </p> <p> CopyRight © 2007-2016 南京新与力文化传播有限公司 diff --git a/package.json b/package.json index 9a30161..c1ad70b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "yohobuy-node", - "version": "5.9.1", + "version": "5.9.4", "private": true, "description": "A New Yohobuy Project With Express", "repository": { diff --git a/public/img/layout/police.png b/public/img/layout/police.png new file mode 100644 index 0000000..9f76394 Binary files /dev/null and b/public/img/layout/police.png differ diff --git a/public/js/brands/brands.page.js b/public/js/brands/brands.page.js index 58a7975..23516da 100644 --- a/public/js/brands/brands.page.js +++ b/public/js/brands/brands.page.js @@ -160,8 +160,14 @@ function bindHoverEvent() { $brand.unbind('mouseenter').unbind('mouseleave').hover(function() { var $this = $(this); var key = $this.attr('data-key'); + var options; - var options = { + // 全球购品牌不展示品牌简介 + if (+key < 0) { + return; + } + + options = { url: '/brands/brandinfo', type: 'get', data: { diff --git a/public/js/common.js b/public/js/common.js index 16634df..f3002fe 100644 --- a/public/js/common.js +++ b/public/js/common.js @@ -114,7 +114,7 @@ function getShoppingKey() { a.src = j; m.parentNode.insertBefore(a, m); }(window, document, 'script', (document.location.protocol === 'https:' ? 'https:' : 'http:') + '//' + // eslint-disable-line - 'cdn.yoho.cn/yas-jssdk/2.4.1/yas.js', '_yas')); // eslint-disable-line + 'cdn.yoho.cn/yas-jssdk/2.4.2/yas.js', '_yas')); // eslint-disable-line (function() { var uid = getUid(); @@ -124,7 +124,7 @@ function getShoppingKey() { window._ozuid = uid; // 暴露ozuid if (window._yas) { - window._yas(1 * new Date(), '2.4.1', 'yohobuy_web', uid, '', ''); + window._yas(1 * new Date(), '2.4.2', 'yohobuy_web', uid, '', ''); } }()); diff --git a/public/js/product/detail.page.js b/public/js/product/detail.page.js index 44ba23c..365859f 100644 --- a/public/js/product/detail.page.js +++ b/public/js/product/detail.page.js @@ -1519,45 +1519,29 @@ function initPageYas() { yas.givePoint('YB_CHOOSE_FOR_YOU_Y', loadYas); } -// 店铺推荐 +// 店铺推荐 改为后台直出 function loadRecommend() { - return $.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 && pro.length !== 0) { - $('#recommend-shop').removeClass('hide'); - $('#recommend-content').append(html); - $('.recommend-slider').slider2({ - shownum: 5, - isCircle: true - }); - $('.recommend-slider .img-item .goods-id').each(function() { - $goodsIdArr.push($(this).html()); - }); - } else { - $('.bottom-title').eq(0).removeClass('bottom-cur').addClass('hide'); - $('.bottom-title').eq(1).addClass('bottom-cur'); - $('.bottom-title').filter('.change').addClass('hide'); + var imgItem = $('.recommend-slider .img-item'), + $bottomTitle = $('.bottom-tab .bottom-title'); - $('#recommend-shop').remove(); - $('.individual-comment .latest-walk').show(); - fetchLatestWalk(); // eslint-disable-line - } + if (imgItem.length !== 0) { - // 页面加载完,埋点 - initPageYas(); - }); + $('.recommend-slider .img-item .goods-id').each(function() { + $goodsIdArr.push($(this).html()); + }); + } else { + $bottomTitle.eq(0).removeClass('bottom-cur').addClass('hide'); + $bottomTitle.eq(1).addClass('bottom-cur'); + $bottomTitle.filter('.change').addClass('hide'); + + $('#recommend-shop').remove(); + $('.individual-comment .latest-walk').show(); + fetchLatestWalk(); // eslint-disable-line + } + + // 页面加载完,埋点 + initPageYas(); } // 点击为您推荐商品埋点 @@ -1859,14 +1843,14 @@ $('.bottom-tab').on('click', '.bottom-title', function() { $recommendComment.slideDown(SLIDETIME); $latestWalk.slideUp(SLIDETIME); - $('.change').removeClass('hide'); + $(this).siblings('.change').removeClass('hide'); } else { // 最近游览 window.fetchLatestWalk(); // eslint-disable-line $recommendComment.slideUp(SLIDETIME); $latestWalk.slideDown(SLIDETIME); - $('.change').addClass('hide'); + $(this).siblings('.change').addClass('hide'); } }); @@ -1983,6 +1967,16 @@ $(function() { } }); }); + + // 猜你喜欢、店铺推荐初始化, + $('.recommend-slider-alike').slider2({ + shownum: 5, + isCircle: true + }); + $('.recommend-slider').slider2({ + shownum: 5, + isCircle: true + }); }); yasAtBottom.yasBottom(); diff --git a/public/scss/common/_footer.css b/public/scss/common/_footer.css index 3472e7d..e19bc76 100644 --- a/public/scss/common/_footer.css +++ b/public/scss/common/_footer.css @@ -346,6 +346,13 @@ padding: 0 10px; } } + + .police { + background: resolve(layout/police.png) no-repeat; + height: 20px; + display: inline-block; + padding-left: 25px; + } } .right-floating-layer { diff --git a/public/scss/product/_detail.css b/public/scss/product/_detail.css index 8e27309..607b7c2 100644 --- a/public/scss/product/_detail.css +++ b/public/scss/product/_detail.css @@ -1009,7 +1009,8 @@ } } - .bottom-tab { + .bottom-tab, + .alike-title { .bottom-title { font-size: 15px; display: inline-block; @@ -1804,6 +1805,31 @@ } } + .recommend-keywords { + margin-top: 30px; + margin-bottom: 20px; + border: 1px #e0e0e0 solid; + + h3 { + height: 46px; + border-bottom: 1px #e0e0e0 solid; + line-height: 44px; + background: #f5f5f5; + text-align: center; + font-size: 15px; + } + + p { + padding: 10px; + + a { + display: inline-block; + margin: 5px 15px; + font-size: 12px; + } + } + } + .support-salereturned-service { $service: product/service.png; @@ -2083,6 +2109,20 @@ } } } + + .alike-title { + margin-top: 30px; + } + + .alike { + .recommend-content { + height: 340px; + + li { + height: 340px; + } + } + } } .coupon-big {