Authored by yyq

Merge branch 'feature/seoHot' into release/6.6wp

/*
* @Author: yyq
* @Date: 2018-05-07
*/
'use strict';
const seoModel = require('../models/seo-service'); // seo 页 model
const hot = (req, res, next) => {
return req.ctx(seoModel).getHotKeywordDate(req.params.id, req.query, req.yoho.channel).then(result => {
res.render('seo/hot', result);
}).catch(next);
};
module.exports = {
hot
};
... ...
const redis = global.yoho.redis;
const helpers = global.yoho.helpers;
const logger = global.yoho.logger;
const _ = require('lodash');
const headerModel = require('../../../doraemon/models/header');
const SearchApi = require('./search-api');
const searchHandler = require('./search-handler');
const utils = '../../../utils';
const productProcess = require(`${utils}/product-process-simple`);
const _setHotKeywordData = (result, params, channel) => {
let changeQuery = Object.assign({}, params);
let finalResult = {
headerData: Object.assign(result[0].headerData, {
header: true
})
};
_.unset(changeQuery, 'query');
// 获取商品数据和顶部筛选条件
if (result[1].code === 200) {
let data = result[1].data;
Object.assign(finalResult,
searchHandler.handlePathNavData({total: data.total}, params, 'search', channel),
{
product: {
opts: searchHandler.handleOptsData(changeQuery, data.total),
totalCount: data.total,
footPager: searchHandler.handlePagerData(data.total, changeQuery),
goods: productProcess.processProductList(data.product_list,
Object.assign({showDiscount: false, from: {type: 'hot', params: params}}, params)),
hasNextPage: searchHandler.handleNextPage(changeQuery, data.total)
}
}
);
finalResult.hotBrands = _.get(data, 'filter.brand', []);
finalResult.hotBrands.forEach((val) => {
val.href = helpers.urlFormat(`/list/bd${val.id}.html`);
return val;
});
finalResult.criteo = {skn: searchHandler.getCriteo(_.get(finalResult.search, 'goods'))};
}
if (result[2].code === 200) {
let data = result[2].data;
finalResult.latestWalkExtra = [{
extraTabName: '相关推荐',
extraGoodsList: productProcess.processProductList(data.product_list,
Object.assign({showDiscount: false, from: {type: 'hot', params: params}}, params))
}];
}
return finalResult;
};
module.exports = class extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
this.searchApi = new SearchApi(ctx);
}
getSearchProduct(params, channel) {
let searchParams = searchHandler.getSearchParams(params);
switch (channel) {
case 'boys':
searchParams.physical_channel = 1;
break;
case 'girls':
searchParams.physical_channel = 2;
break;
case 'kids':
searchParams.physical_channel = 3;
break;
case 'lifestyle':
searchParams.physical_channel = 4;
break;
default:
break;
}
searchParams.need_filter = 'yes';
return Promise.all([
headerModel.requestHeaderData(channel),
this.searchApi.getSeoProductList(searchParams, 'fuzzySearch'),
this.searchApi.getSeoProductList(Object.assign(searchParams, {
order: 's_n_desc',
limit: 5
}), 'fuzzySearch'),
]).then(result => {
return _setHotKeywordData(result, params, channel);
});
}
getHotKeywordDate(id, params, channel) {
return redis.all([
['get', `global:yoho:seo:hot:keywords:id:${id}`]
]).then(redisData => {
let keyword = redisData[0];
try {
keyword = JSON.parse(keyword);
} catch (e) {
logger.debug('getProductList cache data parse fail.');
}
if (!_.get(keyword, 'name')) {
return Promise.reject(`cannot find hot keywords by id(${id})`);
}
params.query = keyword.name;
return this.getSearchProduct(params, channel).then(result => {
result.hotKeys = (keyword.data || []).map(val => {
val.href = helpers.urlFormat(`/hot/${val.id}.html`);
return val;
});
result.keyword = keyword;
result.latestWalk = 5;
return result;
});
});
}
};
... ...
... ... @@ -53,6 +53,9 @@ const globalCtrl = require(`${cRoot}/global`);
// 店铺controller
const shop = require(`${cRoot}/shop`);
// seo controller
const seo = require(`${cRoot}/seo`);
// 商品促销routers
router.get('/sale', sale.index); // sale 首页
router.get('/sale/vip', sale.vip); // VIP 活动专区
... ... @@ -118,6 +121,7 @@ router.get('/search/history', search.searchHistory); // 搜索历史提示
router.get('/search/less/recommend', search.searchLessRecommend);// 搜索少或无 有可能喜欢
router.get('/search/keyword/:id', search.keyword);
router.get('/search/chanpin/:id', search.keyId);
router.get('/search/hot/:id.html', '/hot/:id.html', seo.hot);
// 新品到着
router.get('/list/new', list.newWithChannel);
... ...
<div class="yoho-page seo-hot-page product-list-page">
{{> common/path-nav}}
<div class="clearfix">
<div class="left-content">
<div class="hot-sort">
{{# keyword}}
<div class="sort-intro">
<div class="inline">
<p class="name">
<span class="cn">{{name}}</span>
{{# nameEn}}<span class="en">{{.}}</span>{{/ nameEn}}
</p>
{{# describe}}<p class="desc">{{.}}</p>{{/ describe}}
{{#if list}}
<ul class="key">
{{# list}}
<li><a href="{{href}}">{{name}}</a></li>
{{/ list}}
</ul>
{{/if}}
</div>
</div>
<img class="thumb" src="{{image2 goods_img}}">
{{/ keyword}}
</div>
{{# product}}
{{> product/standard-content}}
{{/ product}}
</div>
<div class="right-content">
<div class="hot-block">
<p class="title">热门关键词</p>
<p class="hot-key">
{{# hotKeys}}
<a href="{{href}}">{{keyword}}</a>
{{/ hotKeys}}
</p>
</div>
<div class="hot-block">
<p class="title">热门品牌</p>
{{# hotBrands}}
<a href="{{href}}" class="brand-item" target="_blank" title="{{brand_name_cn}}">
<img src="{{image2 brand_ico w=138 h=70}}" alt="{{brand_name_cn}} {{brand_keyword}}">
</a>
{{/ hotBrands}}
</div>
</div>
</div>
{{> product/latest-walk goodsInfo=@root.recommendGoodsInfo}}
</div>
... ...
... ... @@ -7,6 +7,9 @@
<span class="about tab-item">相关推荐</span>
{{/if}}
{{# latestWalkExtra}}
<span class="tab-item extra-tab-item" data-key="{{@index}}">{{extraTabName}}</span>
{{/ latestWalkExtra}}
<div class="bottom-line"></div>
</div>
<div class="bottom-tab-cont">
... ... @@ -39,5 +42,24 @@
</p>
</div>
{{/if}}
{{# latestWalkExtra}}
<div class="latest-walk-extra-area extra-area-{{@index}}">
<div class="goods clearfix">
{{# extraGoodsList}}
<div class="good">
<a href="{{url}}" target="_blank" title="{{product_name}}">
<img class="lazy" data-original="{{image2 thumb w=280 h=382}}" alt="{{product_name}}" />
</a>
<a class="name" href="{{url}}" target="_blank">{{product_name}}</a>
<p class="price">
<span class="market-price">¥{{round market_price 2}}</span>
<span class="sale-price">¥{{round sales_price 2}}</span>
</p>
</div>
{{/ extraGoodsList}}
</div>
</div>
{{/ latestWalkExtra}}
</div>
{{/unless}}
... ...
... ... @@ -16,6 +16,7 @@
@import "new-arrive";
@import "good-slide";
@import "../variables";
@import "seo/index";
.product-page {
.list-left {
... ...
.seo-hot-page {
width: 1150px;
margin: 0 auto;
.left-content {
float: left;
width: 970px;
}
.hot-sort {
width: 100%;
position: relative;
.sort-intro {
width: 488px;
height: 300px;
line-height: 300px;
border: 1px solid #eaeceb;
box-sizing: border-box;
}
.inline {
width: 100%;
padding: 0 50px;
line-height: 1;
text-align: center;
display: inline-block;
box-sizing: border-box;
vertical-align: middle;
}
.name {
font-size: 30px;
font-weight: 700;
text-align: center;
margin-top: 0;
.en {
width: 100%;
font-size: 14px;
display: block;
}
}
.desc {
margin-top: 15px;
color: #666;
font-size: 12px;
line-height: 1.5;
}
.key {
margin-top: 30px;
> li {
width: 33.33%;
text-align: center;
float: left;
font-size: 12px;
line-height: 20px;
text-decoration: underline;
}
a {
color: #069;
}
}
.thumb {
width: 480px;
height: 300px;
position: absolute;
top: 0;
right: 0;
}
}
.right-content {
float: right;
width: 160px;
$border-color: #dfdfdf;
.hot-block {
font-size: 12px;
border: 1px solid $border-color;
margin-bottom: 20px;
.title {
line-height: 40px;
font-weight: bold;
background-color: #eaeceb;
padding-left: 10px;
}
.hot-key {
line-height: 26px;
padding: 12px 6px 12px 10px;
border-top: 1px solid $border-color;
> a {
margin-right: 4px;
display: inline-block;
}
}
.brand-item {
height: 100px;
padding: 15px 10px;
display: block;
box-sizing: border-box;
border-top: 1px solid $border-color;
img {
width: 100%;
height: 100%;
display: block;
}
}
}
}
.bottom-tab-cont {
padding-bottom: 20px;
.latest-walk-extra-area {
display: none;
}
.goods {
width: 110%;
height: auto;
margin: 20px 0;
.good {
float: left;
width: 220px;
margin-right: 14px;
font-size: 12px;
text-align: center;
img {
width: 220px;
height: 300px;
display: block;
}
.name {
display: block;
max-width: 150px;
height: 18px;
line-height: 16px;
margin: 5px auto;
color: #222;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.market-price {
color: #999;
margin-right: 5px;
text-decoration: line-through;
}
.sale-price {
color: #000;
font-weight: 700;
}
}
}
}
}
... ...