Authored by htoooth

Merge branch 'master' into feature/update-lib

Showing 89 changed files with 2423 additions and 715 deletions
... ... @@ -188,7 +188,7 @@ const guangMap = (req, res, next) => {
const newsMap = (req, res, next) => {
req.ctx(siteMapService).newsList(1, []).then(rdata => {
return _createSitemap(req, res, rdata, 'https://www.yohobuy.com/news/', '.html');
return _createSitemap(req, res, rdata, 'https://www.yohobuy.com/guang/news/', '.html');
}).catch(next);
};
... ...
... ... @@ -47,7 +47,7 @@ module.exports = class extends global.yoho.BaseModel {
}
lres = lres.concat(_.map(artList, (art) => {
return `${art.id}_${art.cid}`;
return `${art.id}_${art.cid}_${art.app}`;
}));
rdata = [];
... ...
'use strict';
const _ = require('lodash');
const headerModel = require('../../../doraemon/models/header');
const aboutModel = require('../models/about');
let responseData = {
module: 'about',
... ... @@ -10,7 +13,7 @@ let responseData = {
* 关于有货
*/
const yohobuy = (req, res, next) => {
let channel = req.cookies._Channel || 'boys';
let channel = req.yoho.channel || 'boys';
headerModel.requestHeaderData(channel).then(result => {
responseData.headerData = result.headerData;
... ... @@ -23,7 +26,7 @@ const yohobuy = (req, res, next) => {
* 新力传媒
*/
const newpower = (req, res, next) => {
let channel = req.cookies._Channel || 'boys';
let channel = req.yoho.channel || 'boys';
headerModel.requestHeaderData(channel).then(result => {
responseData.headerData = result.headerData;
... ... @@ -36,7 +39,7 @@ const newpower = (req, res, next) => {
* 联系我们
*/
const contact = (req, res, next) => {
let channel = req.cookies._Channel || 'boys';
let channel = req.yoho.channel || 'boys';
headerModel.requestHeaderData(channel).then(result => {
responseData.headerData = result.headerData;
... ... @@ -49,7 +52,7 @@ const contact = (req, res, next) => {
* 隐私条款
*/
const privacy = (req, res, next) => {
let channel = req.cookies._Channel || 'boys';
let channel = req.yoho.channel || 'boys';
headerModel.requestHeaderData(channel).then(result => {
responseData.headerData = result.headerData;
... ... @@ -62,12 +65,43 @@ const privacy = (req, res, next) => {
* 友情链接
*/
const link = (req, res, next) => {
let channel = req.cookies._Channel || 'boys';
let channel = req.yoho.channel || 'boys';
headerModel.requestHeaderData(channel).then(result => {
responseData.headerData = result.headerData;
Promise.all([
headerModel.requestHeaderData(channel),
req.ctx(aboutModel).link(),
]).then(result => {
responseData.headerData = _.get(result, '[0].headerData');
res.render('link', responseData);
res.render('link', Object.assign(_.get(result, '[1]', {}), responseData));
}).catch(next);
};
/**
* 品类大全
*/
const category = (req, res, next) => {
let channel = req.yoho.channel || 'boys';
return Promise.all([
headerModel.requestHeaderData(channel),
req.ctx(aboutModel).getCategoryDataWithCache(channel)
]).then(result => {
res.render('category', Object.assign(result[1], responseData, result[0]));
}).catch(next);
};
/**
* 产品大全
*/
const chanpin = (req, res, next) => {
let channel = req.yoho.channel || 'boys';
return Promise.all([
headerModel.requestHeaderData(channel),
req.ctx(aboutModel).getChanpinData(channel)
]).then(result => {
res.render('chanpin', Object.assign(result[1], responseData, result[0]));
}).catch(next);
};
... ... @@ -76,5 +110,7 @@ module.exports = {
newpower,
contact,
privacy,
link
link,
category,
chanpin
};
... ...
/**
* about model
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2017/11/20
*/
const _ = require('lodash');
const cache = global.yoho.cache;
const logger = global.yoho.logger;
const helpers = global.yoho.helpers;
const redis = global.yoho.redis;
const handleStaticUrl = require(`${global.utils}/parameter`).fullParamToMinPath;
const hotBrandsModel = require('../../../doraemon/models/hot-brands');
const CACHE_TIME_S = 60 * 60;
const indexUrl = {
boys: helpers.urlFormat('/'),
girls: helpers.urlFormat('/woman'),
kids: helpers.urlFormat('/kids'),
lifestyle: helpers.urlFormat('/lifestyle')
};
module.exports = class extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
}
getCategoryFromApi(channel) {
return this.get({data: {
method: 'web.regular.groupsort.sale',
sales: 'Y', // 在销售商品分类
status: 1, // 上架商品分类
stocknumber: 1, // 过滤掉已售罄
yh_channel: channel
}, param: {cache: true}});
}
getCategoryData(channel) {
return Promise.all([
this.getCategoryFromApi(1),
this.getCategoryFromApi(2),
this.getCategoryFromApi(3),
this.getCategoryFromApi(4),
hotBrandsModel.hotBrands()
]).then(result => {
const nameMap = ['男生', '女生', '潮童', '创意生活'];
const enMap = ['boys', 'girls', 'kids', 'lifestyle'];
const genderMap = ['1,3', '2,3'];
const baseUrl = '/list';
const hotBrands = result.pop();
let categoryList = [];
_.forEach(result, (res, index) => {
if (res.code !== 200) {
return;
}
let list = [],
gender = genderMap[index],
ename = enMap[index];
_.forEach(res.data || [], cate => {
let sub = [];
let seatUrl = helpers.urlFormat(handleStaticUrl(baseUrl, {
category_id: '{categoryId}',
gender: gender,
channel: ename
}));
_.forEach(cate.sub, scate => {
sub.push({
name: scate.category_name,
url: seatUrl.replace('{categoryId}', scate.category_id)
});
});
list.push({
title: cate.category_name,
sub: sub
});
});
categoryList.push({
channelName: nameMap[index],
list: list
});
});
let upChannel = _.toUpper(channel);
return {
pathNav: [
{pathTitle: `${upChannel}首页`, name: `${upChannel}首页`, href: indexUrl[channel]},
{pathTitle: '全部分类', name: '全部分类'}
],
hotBrands,
categoryList
};
});
}
getCategoryDataWithCache(channel) {
let cacheKey = 'seo_category_group_map';
return cache.get(cacheKey).then(cdata => {
let cdataObj;
if (cdata) {
try {
cdataObj = JSON.parse(cdata);
} catch (e) {
logger.debug('category map cache data parse fail.');
}
}
if (cdataObj) {
return cdataObj;
}
return this.getCategoryData(channel).then(list => {
if (list && list.length) {
cache.set(cacheKey, list, CACHE_TIME_S);
}
return list;
});
}).catch(err => {
logger.debug(`get category map cache data fail:${err.toString()}`);
return this.getCategoryData(channel);
});
}
getChanpinData(channel) {
return Promise.all([
redis.all([['get', 'global:yoho:seo:goodsAll']]),
hotBrandsModel.hotBrands()
]).then(result => {
let upChannel = _.toUpper(channel);
let chanpinList = [];
try {
chanpinList = JSON.parse(_.get(result, '[0][0]'));
} catch (e) {
logger.debug('chanpin all goods data parse fail.');
}
return {
pathNav: [
{pathTitle: `${upChannel}首页`, name: `${upChannel}首页`, href: indexUrl[channel]},
{pathTitle: '产品大全', name: '产品大全'}
],
hotBrands: result[1],
chanpinList
};
});
}
link() {
return redis.all([
['get', 'friend:text:links'],
['get', 'friend:img:links']
]).then(redisData => {
let textLinks = [],
imgLinks = [];
try {
textLinks = JSON.parse(redisData[0]);
} catch (e) {
logger.error(`friend text links parse error : ${JSON.stringify(e)}`);
}
try {
imgLinks = JSON.parse(redisData[1]);
} catch (e) {
logger.error(`friend img links parse error : ${JSON.stringify(e)}`);
}
return {
textLinks: _.sortBy(textLinks, o => {
return -o.sort;
}),
imgLinks: _.sortBy(imgLinks, o => {
return -o.sort;
})
};
});
}
};
... ...
... ... @@ -13,5 +13,8 @@ router.get('/newpower.html', aboutCtrl.newpower);
router.get('/contact.html', aboutCtrl.contact);
router.get('/privacy.html', aboutCtrl.privacy);
router.get('/link.html', aboutCtrl.link);
router.get('/cate', aboutCtrl.category);
router.get('/cpdq', aboutCtrl.chanpin);
module.exports = router;
... ...
<div class="category-map-page center-content yoho-page">
{{> common/path-nav}}
<div class="list-block">
<h1 class="main-title">全部分类</h1>
{{# categoryList}}
<p class="channel-name">{{channelName}}</p>
{{# list}}
<p><label class="left-title">{{title}}:</label>
{{# sub}}<a href="{{url}}" target="_blank">{{name}}</a>{{/ sub}}
</p>
{{/ list}}
{{/ categoryList}}
</div>
{{#if hotBrands}}
<div class="hot-brands clearfix">
{{# hotBrands}}
<a href="{{url}}" title="{{title}}" target="_blank">
<img src="{{image image}}" alt="{{title}}">
</a>
{{/ hotBrands}}
</div>
{{/if}}
</div>
... ...
<div class="chanpin-map-page center-content yoho-page">
{{> common/path-nav}}
<div class="chanpin-block">
<h1 class="main-title">产品大全</h1>
<ul class="list-block clearfix">
{{# chanpinList}}
<li><a href="//www.yohobuy.com/chanpin/{{id}}.html" title="{{keyword}}" target="_blank">{{keyword}}</a></li>
{{/ chanpinList}}
</ul>
</div>
{{#if hotBrands}}
<div class="hot-brands clearfix">
{{# hotBrands}}
<a href="{{url}}" title="{{title}}" target="_blank">
<img src="{{image image}}" alt="{{title}}">
</a>
{{/ hotBrands}}
</div>
{{/if}}
</div>
... ...
... ... @@ -14,15 +14,33 @@
<br>
<br>
<h2>文字链接:</h2>
<ul>
<li><a href="http://b2b.hc360.com" target="_blank">慧聪网供应信息</a></li>
<li><a href="http://www.manmanbuy.com" target="_blank">比价网</a></li>
<li><a href="http://www.hao224.com" target="_blank">团购导航</a></li>
<li><a href="//www.kuaidi100.com" target="_blank">快递查询</a></li>
<ul class="link-text clearfix">
{{# textLinks}}
<li><a href="{{link}}" target="_blank">{{name}}</a></li>
{{/ textLinks}}
</ul>
<h2>图片链接:</h2>
<ul class="linkpic">
<ul class="link-img clearfix">
{{# imgLinks}}
<li>
<a href="{{link}}" target="_blank">
<img src="{{img}}" title="{{name}}" alt="{{name}}">
</a>
</li>
{{/ imgLinks}}
</ul>
<div class="link-apply">
<p>
友情链接要求:<br>
1、违反我国现行法律的或含有令人不愉快内容的网站勿扰。<br>
2、百度收录量大于5万,来自百度的日流量大于1万(以爱站数据为准)。<br>
3、百度权重值大于等于5。<br><br>
欢迎交换友情链接,请通过以下方式联系。<br>
QQ :1092657603(标注交换链接,带上网址)
</p>
</div>
</div>
</div>
</div>
... ...
... ... @@ -73,28 +73,28 @@ module.exports = class extends global.yoho.BaseModel {
seoMap() {
return {
boys: {
title: '品牌一览|男装品牌排行榜,男装品牌大全|YOHO!BUY 有货 100%正品保证',
keywords: '品牌一览,男装品牌,男装品牌排行榜,男装品牌大全,YOHO!BUY 有货',
description: 'YOHO!BUY 有货男装品牌一览汇集国内国际各大男装品牌大全,为广大爱好时尚的男士青年提供品牌男装、' +
'休闲男装、商务男装.YOHO!BUY 有货,100%正品保证'
title: '【男生潮流品牌一览】潮流品牌大全,热销潮流品牌-有货网品牌一览',
keywords: '潮流品牌一览,潮流品牌大全,热销潮牌',
description: '有货网品牌大全汇聚服饰、鞋履、包袋,配饰等大牌,潮流品牌排行榜包括vans、Lee、puma、' +
'reebok、AKOP、Levi\'s等国内外知名潮流品牌,够潮,就上有货网!'
},
girls: {
title: '品牌一览|女装品牌排行榜,女装品牌大全|YOHO!BUY 有货 100%正品保证',
keywords: '品牌一览,女装品牌,女装品牌排行榜,女装品牌大全,YOHO!BUY 有货',
description: 'YOHO!BUY 有货女装品牌一览汇集国内国际各大女装品牌,为广大爱美女生提供品牌女装、休闲女装、' +
'商务女装.买品牌女装就上YOHO!BUY 有货,100%正品保证'
title: '【男生潮流品牌一览】潮流品牌大全,热销潮流品牌-有货网品牌一览',
keywords: '潮流品牌一览,潮流品牌大全,热销潮牌',
description: '有货网品牌大全汇聚服饰、鞋履、包袋,配饰等大牌,潮流品牌排行榜包括vans、Lee、puma、' +
'reebok、AKOP、Levi\'s等国内外知名潮流品牌,够潮,就上有货网!'
},
kids: {
title: '品牌一览|童装童鞋品牌,儿童鞋包配饰排行榜,潮童品牌大全|YOHO!BUY 有货 100%正品保证',
keywords: '童装品牌,童装童鞋排行榜,儿童鞋包配饰排行榜,潮童品牌大全,品牌一览,YOHO!BUY 有货',
description: 'YOHO!BUY 有货童装品牌一览汇集国内国际各大童装品牌大全,为广大爱好潮流的儿童提供品牌童装、童鞋,' +
'儿童鞋包配饰.YOHO!BUY 有货,100%正品保证'
title: '【男生潮流品牌一览】潮流品牌大全,热销潮流品牌-有货网品牌一览',
keywords: '潮流品牌一览,潮流品牌大全,热销潮牌',
description: '有货网品牌大全汇聚服饰、鞋履、包袋,配饰等大牌,潮流品牌排行榜包括vans、Lee、puma、' +
'reebok、AKOP、Levi\'s等国内外知名潮流品牌,够潮,就上有货网!'
},
lifestyle: {
title: '品牌一览|数码3c,居家,玩具娱乐,文具,美妆品牌|YOHO!BUY 有货 100%正品保证',
keywords: '数码3c品牌,居家品牌,玩具娱乐品牌,文具品牌,美妆品牌',
description: 'YOHO!BUY 有货女装品牌一览汇集国内国际各大数码3c品牌,居家品牌,玩具娱乐品牌,文具品牌,' +
'美妆品牌.买创意生活家居就上YOHO!BUY 有货,100%正品保证'
title: '【男生潮流品牌一览】潮流品牌大全,热销潮流品牌-有货网品牌一览',
keywords: '潮流品牌一览,潮流品牌大全,热销潮牌',
description: '有货网品牌大全汇聚服饰、鞋履、包袋,配饰等大牌,潮流品牌排行榜包括vans、Lee、puma、' +
'reebok、AKOP、Levi\'s等国内外知名潮流品牌,够潮,就上有货网!'
},
'boys-plusstar': {
title: '品牌plusstar,男装潮流品牌简介|YOHO!BUY有货',
... ... @@ -107,6 +107,26 @@ module.exports = class extends global.yoho.BaseModel {
keywords: '品牌plusstar,女装潮流品牌简介',
description: 'YOHO!BUY 有货女装品牌一览汇集国内国际各大女装品牌,为广大爱美女生提供品牌女装、' +
'休闲女装、商务女装.买品牌女装就上YOHO!BUY 有货,100%正品保证'
},
'plusstar-id1': {
title: '【设计新潮】热销新潮品牌,新潮品牌一览-YOHO!BUY 有货',
keywords: '设计新潮、新潮品牌、新潮店铺',
description: '有货网设计新潮品牌,提供一系列国内外知名潮流品牌,潮流品牌店铺,,想了解更多新潮品牌就来有货网!'
},
'plusstar-id2': {
title: '【潮流经典】潮流经典品牌大全,热销经典品牌-YOHO!BUY 有货',
keywords: '潮流经典,经典品牌,潮流店铺',
description: '有货网潮流经典品牌,提供一系列国内外经典潮流品牌,经典潮流品牌店铺,想了解更多经典潮流品牌就来有货网!'
},
'plusstar-id3': {
title: '【明星潮品】明星品牌大全,知名明星潮流品牌-YOHO!BUY 有货',
keywords: '明星潮品,明星品牌,明星潮流店铺',
description: '有货网明星潮品,提供一系列国内外明星潮流品牌,明星潮流品牌店铺,想了解更多明星潮流品牌就来有货网!'
},
'plusstar-id4': {
title: '【原创潮牌】原创潮牌品牌大全,优质潮流品牌-YOHO!BUY 有货',
keywords: '原创潮牌,原创品牌,原创潮流品牌店铺',
description: '有货网原创潮牌,提供最全的国内外原创潮流品牌,原创潮流品牌店铺,想了解更多原创潮流品牌就来有货网!'
}
};
}
... ... @@ -167,7 +187,7 @@ module.exports = class extends global.yoho.BaseModel {
];
// SEO
Object.assign(responseData, that.seoMap[channel]);
Object.assign(responseData, that.seoMap()[channel]);
// 数据出错不cashe
if (_.isEmpty(result[0].headerData) || _.isEmpty(result[1]) || _.isEmpty(result[2])) {
... ... @@ -257,6 +277,7 @@ module.exports = class extends global.yoho.BaseModel {
if (+id !== 0 && items[id]) {
brandType = items[id].brandType;
responseData.plusstarTitle = items[id].name;
}
let plustarList = yield brandsModelCtx.getPlustarList(brandType, gender);
... ... @@ -296,7 +317,8 @@ module.exports = class extends global.yoho.BaseModel {
_.forEach(brandIds, brandId => {
if (brandsInfo[brandId]) {
list[brandId].desc = brandsInfo[brandId].desc;
list[brandId].url = helpers.urlFormat('', {gender: gender}, brandsInfo[brandId].url);
list[brandId].url = helpers.urlFormat(`/shop/${brandsInfo[brandId].brand_domain}-.html`);
}
brands.push(list[brandId]);
});
... ... @@ -324,8 +346,10 @@ module.exports = class extends global.yoho.BaseModel {
// 页码
Object.assign(responseData, pageList);
let seomap = that.seoMap();
// SEO
Object.assign(responseData, that.seoMap[`${channel}-plusstar`] || {});
Object.assign(responseData, seomap[`plusstar-id${id}`] || seomap[`${channel}-plusstar`] || {});
return responseData;
})();
... ...
... ... @@ -9,8 +9,8 @@
<li>
<a href="{{url}}">
<div class="g-mask"></div>
<p class="tips">{{name}}</p>
<img class="lazy" data-original="{{image2 src}}"/>
{{!-- <p class="tips">{{name}}</p> --}}
<img class="lazy" data-original="{{image2 src}}" alt="{{name}}" />
</a>
</li>
{{/each}}
... ... @@ -21,11 +21,16 @@
</div>
</div>
</div>
{{#if plusstarTitle}}
<h1 class="plustar-title">{{plusstarTitle}}</h1>
{{/if}}
<div class="brands-items clearfix">
{{#each items}}
<div class="brands-item clearfix">
<a class="brands-pic" title="{{name}}" href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image2 src}}"/>
<img class="lazy" data-original="{{image2 src}}" alt="{{name}}"/>
</a>
<div class="brand-info">
<a title="{{name}}" href="{{url}}" target="_blank">
... ...
... ... @@ -397,7 +397,7 @@ const formatPromotion = (it, selectedGiftsList) => {
promotionDesc: identIconReplace(it.promotion_desc),
promotionType: it.promotion_type, // 促销类型
// list.yohobuy.com?psp_id=10408
promotionPageUrl: helpers.urlFormat('', {psp_id: tsPromotionIds}, 'list'),
promotionPageUrl: helpers.urlFormat('/list', {psp_id: tsPromotionIds}),
tag: PROMOTION_TYPE_TAG_MAP[it.promotion_type],
isGift: it.promotion_type === 'Gift',
... ... @@ -546,7 +546,7 @@ const formatCart = (cartDataRet, uid, shoppingKey, cartDelList) => {
isEmpty: false,
isLogin: !!uid,
searchUrl: helpers.urlFormat('', null, 'search'), // 搜索链接(再逛逛)
listUrl: helpers.urlFormat('', null, 'list'),
listUrl: helpers.urlFormat('/list'),
viewOrderUrl: helpers.urlFormat('/home/orders', {
t: new Date().getTime()
})
... ...
'use strict';
const headerModel = require('../../../doraemon/models/header');
const headerNav = (req, res, next) => {
let channel = req.query.channel || req.yoho.channel;
headerModel.getHeaderSubNav(channel).then(result => {
let resData = {code: 400};
if (result) {
Object.assign(resData, {
code: 200,
data: result
});
}
res.jsonp(resData);
}).catch(next);
};
module.exports = {
headerNav
};
... ... @@ -19,8 +19,6 @@ const getBanner = require(`${cRoot}/getBanner`);
const passport = require(`${cRoot}/passport`);
const suggestFeedBack = require(`${cRoot}/suggestFeedBack`);
const main = require(`${cRoot}/index`);
router.get('/recentReview', rvCtrl.index); // 最近浏览
router.post('/getRecommend', rvCtrl.getRecommend); // 为你优选
... ... @@ -34,8 +32,6 @@ router.get('/passport', passport.index);
router.get('/suggestfeedback', suggestFeedBack.getFeedBack);
router.get('/header/nav', main.headerNav);
module.exports = router;
... ...
... ... @@ -12,7 +12,6 @@ const guangModel = require('../models/guang-service');
const headerModel = require('../../../doraemon/models/header');
const ghelper = require('../models/guang-helper');
const urlHelper = require('../models/url-helper');
const querystring = require('querystring');
const tdk = require('../../../utils/getTDK');
/**
... ... @@ -80,9 +79,8 @@ exports.index = (req, res, next) => {
* 指定标签的文章列表
*/
exports.tags = (req, res, next) => {
let query = req.query.query = (req.query.query || '').replace(/<|>/ig, '');
let page = req.query.page || 1;
let query = req.query.query = (req.query.query || req.params.query || '').replace(/<|>/ig, '');
let page = req.query.page || req.params.page || 1;
let pageSize = req.query.pageSize || 20;
let type = req.query.type || 0;
... ... @@ -122,7 +120,7 @@ exports.tags = (req, res, next) => {
tag: query,
guangIndexPage: true,
baseUrl: `?${querystring.stringify(req.query)}`,
baseUrl: urlHelper.tagsUrl(query),
pageSize: pageSize,
type: type,
pathNav: pathNav,
... ... @@ -249,7 +247,7 @@ exports.detail = (req, res, next) => {
let promises = [
headerModel.requestHeaderData(channel),
reqCtx.getArticleContent(id),
reqCtx.getArticleContent(id, info.title),
reqCtx.getHotTags(1, 20, channel, isHotDegrade),
reqCtx.getArticleComments(udid, uid, id, page, pageSize),
reqCtx.getArticleBaseInfo(id, uid, udid),
... ... @@ -298,11 +296,8 @@ exports.detail = (req, res, next) => {
};
}
title = `${info.title} | YOHO!BUY有货`;
keywords = info.tag.length > 0 ? `${info.tag}` :
['Yoho! 有货,潮流,时尚,流行,购物,B2C,正品,购物网站,网上购物,货到付款,品牌服饰,男士护肤,',
'黑框眼镜,匡威,板鞋,i.t,izzue,5cm,eastpak,vans,lylescott,g-shock,new balance,lacoste,melissa,',
'casio,卡西欧手表,舒雅,jasonwood,odm,AAAA,香港购物,日本潮流'].join('');
title = `${info.title}-YOHO!BUY 有货网`;
keywords = info.title;
description = info.desc.length > 0 ? `${info.desc}` :
'潮流商品搜索,上衣,衬衫,TEE,卫衣,冲锋衣,风衣,羽绒服,裤子,休闲鞋,板鞋,配饰,复古眼镜';
... ...
... ... @@ -82,11 +82,34 @@ const getArticleUrl = (url, id) => {
return helpers.urlFormat(`/guang/${id}.html`);
};
const guangListSeoMap = {
1001: {
title: '高人气潮流文章,逛人气潮流资讯-YOHO!BUY 有货网',
keywords: '人气潮流文章,潮流人气,逛潮流人气',
description: '有货网每天提供全球人气最高的潮流文章资讯,宣传潮流商品,潮流文化,潮流品牌等信息,想更多了解高人气潮流资讯就来有货网!'
},
2: {
title: '各种潮流搭配,逛潮流搭配资讯-YOHO!BUY 有货网',
keywords: '搭配潮流文章,潮流搭配',
description: '有货网每天提供全球最新最潮的潮流搭配文章资讯,宣传潮流商品,潮流文化,潮流品牌等信息,想更多了解学习潮流搭配资讯就来有货网!'
},
4: {
title: '潮流品牌,逛各种潮流品牌资讯-YOHO!BUY 有货网',
keywords: '逛潮品,潮流潮品,潮品资讯',
description: '有货网每天提供全球最新最潮的潮流潮品文章资讯,宣传潮流商品,潮流文化,潮流品牌等信息,想更多了解学习潮流潮品资讯就来有货网!'
},
22: {
title: '潮流视频,欣赏最新最好玩的潮流视频-YOHO!BUY 有货网',
keywords: '潮流视频,看潮流。',
description: '有货网每天提供全球最新最潮最精彩的潮流视频,宣传潮流商品,潮流文化,潮流品牌等信息,想更多欣赏潮流视频就来有货网!'
}
};
const getIndexSeo = (params, tabs) => {
let tdk = {
title: '逛|逛潮流,逛购物,官方授权正品潮流购物中心|YOHO!BUY有货',
keywords: '逛,逛潮流,逛购物',
description: 'YOHO!BUY有货逛频道,来YOHO!玩潮流!潮搭大解析!年轻人潮流购物中心,中国潮流购物风向标,吴亦凡重磅代言!YOHO!BUY有货100%正品保证,支持货到付款。'
title: '逛潮流,最新原创潮流资讯 |YOHO!BUY有货',
keywords: '潮流资讯,潮流文章,有货潮流分享',
description: '来有货玩潮流,潮流资讯大分享!年轻人潮流购物中心,了解潮流趋势、掌握潮流文化知识信息,尽在有货逛潮流!'
};
params = params || {};
... ... @@ -94,12 +117,8 @@ const getIndexSeo = (params, tabs) => {
if (params.hasOwnProperty('type')) {
let tab = _.find(tabs, {isActive: true});
if (tab && tab.type) {
Object.assign(tdk, {
title: `潮流${tab.type}-|YOHO!BUY有货`,
keywords: `潮流${tab.type}`,
description: `YOHO!BUY有货潮流${tab.type}!`
});
if (tab && tab.typeId) {
Object.assign(tdk, guangListSeoMap[tab.typeId] || {});
}
}
... ... @@ -108,17 +127,17 @@ const getIndexSeo = (params, tabs) => {
const getEditorSeo = (name) => {
return {
title: `潮流编辑${name}|YOHO!BUY有货`,
keywords: `潮流编辑${name}`,
description: `YOHO!BUY有货潮流编辑${name}!`
title: `【${name}】潮流编辑${name}-YOHO!BUY 有货网`,
keywords: ` ${name},潮流编辑${name},潮流编辑`,
description: `有货逛潮流,潮流编辑${name}分享大量原创潮流资讯,掌握大量不同类别的潮流文化知识信息,尽在有货逛潮流。`
};
};
const getTagSeo = (tagName) => {
return {
title: `${tagName}|YOHO!BUY有货`,
keywords: `${tagName}`,
description: `YOHO!BUY有货潮流${tagName}!`
title: `【${tagName}${tagName}潮流资讯-YOHO!BUY 有货网`,
keywords: `${tagName}${tagName}潮流资讯,${tagName}文章`,
description: `来有货逛潮流,${tagName}潮流资讯大分享!了解${tagName}潮流趋势,掌握${tagName}潮流文化知识信息,尽在有货逛潮流。`
};
};
... ...
... ... @@ -79,15 +79,12 @@ module.exports = class extends global.yoho.BaseModel {
}
_formatTag(tagData) {
let name = tagData.name,
param = {
query: name
};
let name = tagData.name;
return {
tag: name,
name: name,
url: helpers.urlFormat('/guang/tags/index', param)
url: encodeURI(helpers.urlFormat(`/guang/tags/${name}/`, null))
};
}
... ... @@ -424,13 +421,11 @@ module.exports = class extends global.yoho.BaseModel {
}).then(res => {
return _.map((res && res.data) || [], it => {
let param = {
query: it.tag_name
};
let name = it.tag_name;
return {
tagName: it.tag_name,
url: helpers.urlFormat('/guang/tags/index', param)
url: encodeURI(helpers.urlFormat(`/guang/tags/${name}/`, null))
};
});
});
... ... @@ -546,6 +541,13 @@ module.exports = class extends global.yoho.BaseModel {
navUrl: urlHelper.listUrl(channel, cat.id)
});
}
list.push({
typeId: 0,
type: '资讯',
isActive: false,
navUrl: helpers.urlFormat('/guang/news')
});
}
return list;
... ... @@ -827,7 +829,7 @@ module.exports = class extends global.yoho.BaseModel {
/**
* 获取文章内容详情
*/
getArticleContent(aid) {
getArticleContent(aid, title) {
let that = this;
let content = [],
... ... @@ -859,6 +861,8 @@ module.exports = class extends global.yoho.BaseModel {
let gpromises = [], ggpromises = [];
if (res && res.code === 200 && res.data) {
let altNum = 0;
_.forEach(res.data, (it) => {
_.forEach(it, (val, key) => {
... ... @@ -875,7 +879,15 @@ module.exports = class extends global.yoho.BaseModel {
let other = _.isFunction(that._articleContentFormat()[key]) ?
that._articleContentFormat()[key](val.data) : '';
content.push(other);
if (other) {
// 前五张图片添加alt
if (altNum < 6 && (other.pic || other.smallPic)) {
other.alt = title;
altNum += other.pic ? 1 : other.smallPic.length;
}
content.push(other);
}
}
});
});
... ... @@ -966,7 +978,6 @@ module.exports = class extends global.yoho.BaseModel {
if (res && res.code === 200 && res.data) {
return _.map(res.data, it => {
it.thumb = it.thumb;
it.url = (it.isGlobal !== 'Y') ? it.url :
helpers.urlFormat('/product/global/list', {brand: it.tbl_id});
... ...
... ... @@ -13,3 +13,7 @@ module.exports.editorUrl = function(channel, authorId) {
module.exports.listUrl = function(channel, type) {
return helpers.urlFormat(`/guang/${channel}-t${type}/`, null);
};
module.exports.tagsUrl = function(query, page) {
return encodeURI(page ? `/guang/tags/${query}-p${page}/` : `/guang/tags/${query}/`);
};
... ...
... ... @@ -16,6 +16,8 @@ router.get(['/', '/index/index'], guangController.index);
router.get(['/detail/:id', '/info/index'], guangController.detail); // guang/info/index
router.get(/^\/([\d]+)(.*)/, guangController.detail);
router.get('/tags/index', guangController.tags);
router.get('/tags/:query-p:page', guangController.tags); // tags 伪静态路由
router.get('/tags/:query', guangController.tags); // tags 伪静态路由
router.get('/Index/editor', guangController.editor);
// ajax
... ...
... ... @@ -18,7 +18,9 @@
<div class="article-status clearfix">
<span class="article-time">{{time}}</span>
<span class="article-click">点击:<em>{{click}}</em></span>
<a href="#comment-info" id="article-comment" class="article-comment"><em class="comment-num">{{commentNum}}</em>条评论</a>
<a href="#comment-info" id="article-comment" class="article-comment" rel="nofollow">
<em class="comment-num">{{commentNum}}</em>条评论
</a>
</div>
</div>
{{/ header}}
... ... @@ -32,7 +34,7 @@
{{/ video}}
{{# pic}}
<div class="article-pic block">
<img class="lazy" data-original="{{image2 .}}">
<img class="lazy" data-original="{{image2 .}}" {{#if ../alt}}alt="{{../alt}}"{{/if}}>
</div>
{{/ pic}}
{{# text}}
... ... @@ -43,7 +45,7 @@
{{#if smallPic}}
<div class="article-small-pic block clearfix">
{{# smallPic}}
<img class="lazy" data-original="{{image2 .}}">
<img class="lazy" data-original="{{image2 .}}" {{#if ../alt}}alt="{{../alt}}"{{/if}}>
{{/ smallPic}}
</div>
{{/if}}
... ... @@ -71,7 +73,7 @@
{{# brands}}
<div class="brand">
<a class="thumb" href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image2 thumb}}">
<img class="lazy" data-original="{{image2 thumb}}" alt="{{name}}">
</a>
<p class="brand-name">{{name}}</p>
</div>
... ... @@ -105,7 +107,7 @@
<ul class="clearfix">
{{# tag}}
<li>
<a href="{{url}}" target="_blank" rel="nofollow">{{name}}</a>
<a href="{{url}}" target="_blank" title="{{name}}" rel="nofollow">{{name}}</a>
</li>
{{/ tag}}
</ul>
... ... @@ -123,7 +125,7 @@
<li>
<a href="{{url}}" target="_blank">
<span class="bg-img">
<img src="{{image2 thumb}}" alt="">
<img src="{{image2 thumb}}" alt="{{title}}">
</span>
<div class="post-title">
<h2>{{title}}</h2>
... ...
... ... @@ -12,7 +12,7 @@
{{/ msgs}}
</div>
{{gpager baseUrl totalRecords=total page=page type="ellipsis" theme="msg-pager"}}
{{spager baseUrl totalRecords=total page=page pageVar="p" type="ellipsis" theme="msg-pager"}}
</div>
<div class="right-side">
{{> right-side}}
... ...
... ... @@ -5,7 +5,7 @@
</div>
<div class="type-icon fashion-man"></div>
<a href="{{url}}" target="_blank">
<img class="lazy{{#if isSquareImg}} square{{/if}}" data-original="{{image2 img}}">
<img class="lazy{{#if isSquareImg}} square{{/if}}" data-original="{{image2 img}}" alt="{{title}}">
{{#if isVideo}}<i class="video-icon"></i>{{/if}}
</a>
</div>
... ...
... ... @@ -19,7 +19,7 @@
<h2 class="hot-title">热门标签</h2>
<div class="hot-tag-list">
{{#hotTags}}
<a class="hot-tag" href="{{url}}" target="_blank" rel="nofollow">
<a class="hot-tag" href="{{url}}" target="_blank">
{{tagName}}
</a>
{{/hotTags}}
... ... @@ -34,7 +34,7 @@
{{# authorArticle}}
{{#if url}}
<div class="ex-reco-item clearfix">
<a class="ex-reco-img" href="{{url}}" target="_blank">
<a class="ex-reco-img" href="{{url}}" target="_blank" title="{{title}}">
<span class="bg-img" style="background-image:url({{image2 img}})"></span>
</a>
<a href="{{url}}" target="_blank">
... ...
... ... @@ -19,7 +19,7 @@ exports.index = (req, res, next) => {
}
return res.render('news-index', Object.assign({
title: '潮流资讯 | ' + (res.locals.title || ''),
title: '资讯 | ' + (res.locals.title || ''),
module: 'news',
page: 'index'
}, result));
... ... @@ -33,10 +33,12 @@ exports.detail = (req, res, next) => {
let channel = req.yoho.channel;
let id = req.params[0] || 0;
let cid = req.params[1] || 0;
let app = req.params[2] || 1;
let query = {
channel: channel,
id: id,
cid: cid,
app: app
};
if (!id || !cid) {
... ...
... ... @@ -7,6 +7,8 @@ const NewsAPi = require('./news-api');
const utils = require('./utils');
const moment = require('moment');
const searchHandler = require('../../product/models/search-handler');
const hotBrandsModel = require('../../../doraemon/models/hot-brands');
const redis = global.yoho.redis;
const BOYS = 'boys';
const GIRLS = 'girls';
... ... @@ -57,9 +59,9 @@ module.exports = class extends global.yoho.BaseModel {
pathTitle: 'YOHO!BUY 有货'
},
{
href: helpers.urlFormat('/news'),
name: '潮流资讯',
pathTitle: '潮流资讯'
href: helpers.urlFormat('/guang/news'),
name: '资讯',
pathTitle: '资讯'
}
]).concat(subNav || []);
... ... @@ -80,7 +82,7 @@ module.exports = class extends global.yoho.BaseModel {
lresult = {
id: articleData.id,
classification: _.get(articleData, 'min_category_name', '') || _.get(articleData, 'category_name', ''),
url: helpers.urlFormat(`/news/${articleData.id}_${articleData.cid}.html`),
url: helpers.urlFormat(`/guang/news/${articleData.id}_${articleData.cid}_${articleData.app}.html`),
img: helpers.image(articleData.image, width, height, 1),
title: articleData.title,
pTime: articleData.update_time && moment(articleData.update_time * 1000).format('YYYY年MM月DD HH:mm'),
... ... @@ -99,7 +101,8 @@ module.exports = class extends global.yoho.BaseModel {
let list = _.map(_.get(res, 'data[0].data', []), (it) => {
return {
img: helpers.image(it.src, 640, 640, 1),
url: it.url
url: it.url,
alt: it.alt
};
});
... ... @@ -121,8 +124,6 @@ module.exports = class extends global.yoho.BaseModel {
getIndexList(channel, param) {
let newsAPi = new NewsAPi(this.ctx);
let params = {
type: 'wechat',
limit: 20,
page: param.page || 1
};
... ... @@ -137,7 +138,11 @@ module.exports = class extends global.yoho.BaseModel {
content_code: ADS_CODE[channel] || ADS_CODE.boys,
isAdDegrade: _.get(this.ctx, 'req.app.locals.pc.guang.removeAd', false)
}),
newsAPi.getPolymerizationList(Object.assign({}, params, {id: ATYPE})),
newsAPi.getPolymerizationList(Object.assign({}, params, {
type: 'wechat',
limit: 20,
id: ATYPE
})),
];
return Promise.all(apiMethod).then(result => {
... ... @@ -168,6 +173,7 @@ module.exports = class extends global.yoho.BaseModel {
title: contents.title,
summary: contents.summary,
tag: contents.tag,
syncTypeName: contents.syncTypeName || 'YOHO潮流志',
time: contents.update_time && moment(contents.update_time * 1000).format('YYYY年MM月DD HH:mm'),
};
let content = utils.filterPhtml(contents.content, [
... ... @@ -176,13 +182,38 @@ module.exports = class extends global.yoho.BaseModel {
'点这里'
]);
return {header: header, content: utils.filterAhtml(content)};
content = utils.filterAhtml(content);
return {header: header, content: utils.imgAlt(content, contents.title, 5)};
}
// 潮流详情
getContentDetail(newsAPi, params) {
return redis.all([
['get', `global:yoho:news:detail:${params.id}-${params.cid}-${params.app}`]
]).then(redisData => {
redisData = JSON.parse(redisData[0] || '{}');
if (!redisData.data) {
return newsAPi.getContentDetail(params);
}
return redisData;
});
}
// 获取热销品牌
_getHotBrands() {
return {recommendKeywords: {
keywordsTitle: '热销品牌',
keywords: _.map(hotBrandsModel.hotBrands(), item => {
return Object.assign({}, item, {keyword: item.title});
})
}};
}
detail(channel, param) {
let params = {
id: param.id,
cid: param.cid
cid: param.cid,
app: param.app,
};
let newsAPi = new NewsAPi(this.ctx);
let apiMethod = [
... ... @@ -196,7 +227,7 @@ module.exports = class extends global.yoho.BaseModel {
content_code: ADS_CODE[channel] || ADS_CODE.boys,
isAdDegrade: _.get(this.ctx, 'req.app.locals.pc.guang.removeAd', false)
}),
newsAPi.getContentDetail(params)
this.getContentDetail(newsAPi, params)
];
return Promise.all(apiMethod).then(result => {
... ... @@ -214,11 +245,14 @@ module.exports = class extends global.yoho.BaseModel {
// 详情页数据
Object.assign(responseData, this._formatDetail(result[3], params));
// 热销品牌
Object.assign(responseData, this._getHotBrands());
// 导航pathNav
let title = _.get(responseData, 'header.title', '潮流资讯详情页');
let title = _.get(responseData, 'header.title', '资讯详情页');
Object.assign(responseData, this.getPathNav(channel, [{
href: helpers.urlFormat('/news'),
href: helpers.urlFormat('/guang/news'),
name: title,
pathTitle: title
}]));
... ...
... ... @@ -23,7 +23,10 @@ const util = {
});
return $.html();
html = $.html();
$ = '';
return html;
},
// 过滤 a标签连接和删除html标签中的script和link脚本
... ... @@ -34,9 +37,33 @@ const util = {
let $ = cheerio.load(html, {decodeEntities: false});
$('a').attr('href', 'javascript:void(0);').css({cursor: 'text'});// eslint-disable-line
$('a:not(.a-anchor)').removeAttr('style').attr('href', 'javascript:void(0);').css({cursor: 'text'});// eslint-disable-line
$('script,link').remove();
return $.html();
html = $.html();
$ = '';
return html;
},
// 过滤 a标签连接和删除html标签中的script和link脚本
imgAlt: (html, alt, num) => {
if (!html) {
return html;
}
let $ = cheerio.load(html, {decodeEntities: false});
_.each($('img').slice(0, num), item => {
let $dom = $(item);
$dom.attr('alt', $dom.attr('alt') || alt);
});
html = $.html();
$ = '';
return html;
}
};
... ...
... ... @@ -13,7 +13,7 @@ const newsController = require(`${cRoot}/index`);
const sitemap = require('../3party/controllers/sitemap');
router.get(['/', '/index/index'], newsController.index);
router.get(/\/([\d]+)_([\d]+).html/, newsController.detail);
router.get(/\/([\d]+)_([\d]+)_([\d]+).html/, newsController.detail);
// seo-站点地图
router.get('/sitemap.xml', sitemap.newsMap);
... ...
<div class="news-detail-page news-page yoho-page clearfix">
{{> common/path-nav}}
<div class="left-side detail-body" data-id="{{id}}">
{{# header}}
<h1 class="detail-title">{{title}}</h1>
<div class="article-info clearfix">
{{#if authorUrl}}
<div class="article-author">
<div class="author-avatar">
<a href="{{authorUrl}}" target="_blank">
<img src="http:{{image2 avatar}}">
</a>
</div>
{{> common/path-nav}}
<div class="left-side detail-body" data-id="{{id}}">
{{# header}}
<h1 class="detail-title">{{title}}</h1>
<div class="article-info clearfix">
{{#if authorUrl}}
<div class="article-author">
<div class="author-avatar">
<a href="{{authorUrl}}" target="_blank">
<img src="http:{{image2 avatar}}">
</a>
</div>
<div class="author-info">
<a class="author-name" href="{{authorUrl}}">{{name}}</a>
</div>
{{/if}}
<div class="article-status clearfix">
{{#if time}}
<span class="article-time">
<i class="iconfont">&#xe625;</i>
{{time}}
</span>
{{/if}}
{{#if click}}
<span class="article-click">点击:<em>{{click}}</em></span>
{{/if}}
{{#if commentNum}}
<a href="#comment-info" id="article-comment" class="article-comment"><em class="comment-num">{{commentNum}}</em>条评论</a>
{{/if}}
</div>
<div class="author-info">
<a class="author-name" href="{{authorUrl}}">{{name}}</a>
</div>
{{/if}}
{{#if syncTypeName}}
<div class="article-source">来源于微信公众号:{{syncTypeName}}</div>
{{/if}}
<div class="article-status clearfix">
{{#if time}}
<span class="article-time">
<i class="iconfont">&#xe625;</i>
{{time}}
</span>
{{/if}}
{{#if click}}
<span class="article-click">点击:<em>{{click}}</em></span>
{{/if}}
{{#if commentNum}}
<a href="#comment-info" id="article-comment" class="article-comment"><em class="comment-num">{{commentNum}}</em>条评论</a>
{{/if}}
</div>
{{/ header}}
<div class="article-main">
{{{content}}}
</div>
{{/ header}}
<div class="article-main">
{{{content}}}
</div>
<div class="right-side detail-side">
{{> news-right-side}}
</div>
</div>
<div class="right-side detail-side">
{{> news-right-side}}
</div>
<div class="hot-brand">
{{> product/rec-keywords}}
</div>
</div>
... ...
... ... @@ -7,12 +7,12 @@
<div class="type-icon fashion-man"></div>
{{/if}}
<a href="{{url}}" target="_blank">
<img class="lazy{{#if isSquareImg}} square{{/if}}" data-original="http:{{image2 img}}">
<img class="lazy{{#if isSquareImg}} square{{/if}}" data-original="http:{{image2 img}}" alt="{{title}}">
{{#if isVideo}}<i class="video-icon"></i>{{/if}}
</a>
</div>
<div class="msg-info">
<a class="msg-title" href="{{url}}" target="_blank">{{title}}</a>
<a class="msg-title" href="{{url}}" target="_blank" title="{{title}}">{{title}}</a>
<p class="msg-app">
{{#if editorUrl}}
<a href="{{editorUrl}}" target="_blank">
... ...
... ... @@ -4,11 +4,11 @@
{{# exRecos}}
<div class="ex-reco-item clearfix">
{{#if img}}
<a class="ex-reco-img" href="{{url}}" target="_blank">
<a class="ex-reco-img" href="{{url}}" target="_blank" title="{{title}}">
<span class="bg-img" style="background-image:url({{image2 img}})"></span>
</a>
{{/if}}
<a href="{{url}}" target="_blank">
<a href="{{url}}" target="_blank" title="{{title}}">
<p class="ex-reco-context">{{title}}</p>
</a>
</div>
... ... @@ -19,7 +19,7 @@
<div class="ads">
{{# ads}}
<a class="ad" href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image2 img}}">
<img class="lazy" data-original="{{image2 img}}" alt="{{alt}}">
</a>
{{/ ads}}
</div>
... ...
... ... @@ -30,9 +30,11 @@ exports.index = (req, res, next) => {
logger.debug(`decodeURIComponent query fail:${e.toString()}`);
}
req.ctx(list).getListDataPre(Object.assign(req.query, {uid: req.user.uid, prid: req.user.prid}),
req.ctx(list).getListData(Object.assign(req.query, {uid: req.user.uid, prid: req.user.prid}),
req.yoho.channel).then(result => {
Object.assign(resData, result);
Object.assign(resData, result, {
pageClass: 'static-list-page'
});
if (qs) {
Object.assign(resData, listSeoMap[qs] || {});
... ...
... ... @@ -60,7 +60,10 @@ exports.discount = (req, res, next) => {
responseData.result = result;
if (result) {
responseData.headerData = result.headerData;
Object.assign(responseData, result.seo || {});
}
res.render('sale/discount', responseData);
}).catch(next);
};
... ...
... ... @@ -12,6 +12,7 @@ const _ = require('lodash');
const helpers = global.yoho.helpers;
const utils = '../../../utils';
const stringCode = require(`${utils}/string-code`);
const parameter = require(`${global.utils}/parameter`);
const config = global.yoho.config;
... ... @@ -106,7 +107,16 @@ const suggest4Old = (req, res, next) => {
};
const searchFilterBrands = (req, res, next) => {
req.ctx(search).getBrands4Filter(Object.assign({}, req.query, {
let params = req.query;
if (params.pathname) {
let path = _.last(_.compact(_.split(params.pathname, '/')));
_.unset(params, 'pathname');
_.assign(params, parameter.minPathToFullParam(path));
}
req.ctx(search).getBrands4Filter(Object.assign({}, params, {
keyword: req.query.query || ''
})).then(result => {
let dest = {
... ...
... ... @@ -436,7 +436,7 @@ function _getSortNavAsync(productInfo, gender) {
// 一级分类
navs.push({
href: helpers.urlFormat('', {msort: sort.sort_id, gender: gender}, 'list'),
href: helpers.urlFormat('/list', {msort: sort.sort_id, gender: gender}),
name: sort.sort_name,
pathTitle: sort.sort_name
});
... ... @@ -445,7 +445,7 @@ function _getSortNavAsync(productInfo, gender) {
let subSort = data[1];
navs.push({
href: helpers.urlFormat('', {msort: sort.sort_id, misort: subSort.sort_id, gender: gender}, 'list'),
href: helpers.urlFormat('/list', {msort: sort.sort_id, misort: subSort.sort_id, gender: gender}),
name: subSort.sort_name,
pathTitle: subSort.sort_name
});
... ...
... ... @@ -148,9 +148,9 @@ const _getProductSeoData = (detail) => {
bn = _.get(detail, 'brand_info.brand_name') || detail.product_source;
resData = {
title: `${bn} | ${gn}正品 | YOHO!BUY 有货`,
keywords: `${bn},${bn}专卖店,${bn}官方授权店,${bn}正品,${bn}打折,${bn}折扣店,${bn}真品,${bn}代购`,
description: `YOHO!BUY 有货-${bn}官方授权店,${gn}图片、报价、介绍。YOHO!BUY 有货${bn}专卖店提供${bn}正品、${bn}真品、 ${bn}打折、${bn}代购等。` // eslint-disable-line
title: `【${bn}${gn} | YOHO!BUY 有货网`,
keywords: `${bn}${bn}价格,${bn}图片${bn}`,
description: `${gn} 有货网仅售${detail.final_price}元,购买正品${bn},了解${bn}商品信息就上有货网!` // eslint-disable-line
};
}
... ... @@ -276,6 +276,8 @@ function getGlobalProductDetailData(skn, channelNum, channel) {
logo: brandInfo.brand_ico
};
detailInfo.productTitle = `${brandInfo.brand_name || detailInfo.product_source}|${detailInfo.product_name}`;
resData.pathNav = _.concat(
homeService.getHomeChannelNav(channel),
[
... ...
/**
* 列表页数据处理
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2017/11/24
*/
'use strict';
const _ = require('lodash');
const helpers = global.yoho.helpers;
const indexUrl = {
boys: helpers.urlFormat('/'),
girls: helpers.urlFormat('/woman'),
kids: helpers.urlFormat('/kids'),
lifestyle: helpers.urlFormat('/lifestyle')
};
const parameter = require(`${global.utils}/parameter`);
// 页面商品数量
const pageSizeType = [40, 100, 200];
const handleFilterUrl = parameter.fullParamToMinPath;
/**
* 根据页面设置面包屑导航
* @type {[type]}
*/
const handlePathNavData = (data, params, page, channel, baseUrl) => {
let rootName = '首页';
if (channel && _.isString(channel)) {
rootName = channel.toUpperCase() + rootName;
}
let pathNav = [{
href: indexUrl[channel],
name: rootName, // '首页',
pathTitle: rootName // '首页'
}];
switch (page) {
case 'search': // 搜索结果提示
if (params.query || params.keywords) {
params.query = params.query || params.keywords;
pathNav.push({
name: '“<span id="nav_keyword">' +
params.query + '</span>”&nbsp;&nbsp;共<span id="nav_keyword_count">' +
data.total + '</span>个结果'
});
} else {
pathNav.push({
name: '所有商品'
});
}
break;
case 'brand': // 品牌
pathNav.push({
name: '品牌一览',
pathTitle: '品牌一览',
href: helpers.urlFormat('/brands')
}, {
name: data.brandNameEn + data.brandNameCn,
pathTitle: data.brandNameEn + data.brandNameCn
});
break;
case 'shop': // 店铺
pathNav.push({
name: data.brandName,
pathTitle: data.brandName
});
break;
case 'new': // 新品到着
pathNav.push({
name: '新品到着',
pathTitle: '新品到着'
});
break;
default: // eslint-disable-line
let navList = [];
_.forEach(data, sort => {
let sortName = sort.category_name,
sortCategoryId = `${sort.category_id}`;
if (`${params.category_id}` === sortCategoryId) {
navList = [{
name: sortName,
pathTitle: sortName
}];
return false;
} else if (!_.isEmpty(sort.sub)) {
_.each(sort.sub, misort => {
let misortName = misort.category_name;
if (`${params.category_id}` === `${misort.category_id}`) {
navList = [{
name: sortName,
href: handleFilterUrl(baseUrl, {category_id: sortCategoryId}),
pathTitle: sortName
}, {
name: misortName,
pathTitle: misortName
}];
return false;
}
});
if (navList.length) {
return false;
}
}
});
if (navList.length) {
pathNav = _.concat(pathNav, navList);
}
break;
}
return {
pathNav: pathNav,
listType: page
};
};
/**
* 处理页面左侧分类筛选数据 new
* @param origin 分类原始数据,一般是接口返回数据中的 group_sort 字段
* @param params 当前 URL 中已有的参数
* @param extra 可以任意传值用来处理特殊情况
* @param {string} [baseUrl] 需要跳转非当前页面传的相对路径(可不传,默认为空字符串)
* @returns {{}}
*/
const handleSortData = (origin, params, originParams, baseUrl) => {
let leftContent = {
sort: { misort: [] },
checked: []
};
let allCount = 0;
let all = [{
name: '全部品类',
num: allCount,
href: handleFilterUrl(baseUrl, params, {}, {msort: true, misort: true, sort: true, category_id: true})
}], list = [];
// 生成占位符的url,不用每次遍历分类都拼接url,?category_id=${category_id}&gender=1,3
const href = handleFilterUrl(baseUrl, params, {category_id: '${category_id}'}, {
msort: true,
misort: true,
sort: true
});
const cid = `${originParams.category_id}`;
_.each(origin, cate => {
let cateActive = cid === `${cate.category_id}`;
let category = {
categoryId: cate.category_id,
name: cate.category_name,
active: cateActive
};
let childList = [{
categoryId: cate.category_id,
name: `全部${cate.category_name}`,
href: href.replace('${category_id}', cate.category_id),
childActive: cateActive
}];
_.each(cate.sub, subCate => {
let subCateActive = cid === `${subCate.category_id}`;
if (subCateActive) {
category.active = true;
}
childList.push({
categoryId: subCate.category_id,
name: subCate.category_name,
href: href.replace('${category_id}', subCate.category_id),
childActive: cid === `${subCate.category_id}`
});
});
category.childList = childList;
list.push(category);
});
leftContent.allSort = {all, list};
return leftContent;
};
class FilterTools {
constructor(origin, params, baseUrl) {
this.origin = origin;
this.params = params;
this.baseUrl = baseUrl;
}
handleFilterCheckedConditions() {
let {baseUrl, origin, params} = this;
const conditions = [];
const customPrice = {
min: '',
max: ''
};
const filter = _.get(origin, 'filter', {});
_.each(params, (v, k) => {
const condition = {};
if (k === 'price') {
if (filter.priceRange[params.price]) {
condition.name = filter.priceRange[params.price].replace('¥', '¥');
} else {
const prices = _.split(params.price, ',');
if (prices.length === 1 || (prices[0] && !prices[1])) {
condition.name = `¥${prices[0] || prices[1]}以上`;
customPrice.min = prices[0] || prices[1];
} else {
condition.name = `¥${prices[0] || 0}-${prices[1]}`;
customPrice.min = prices[0] || '';
customPrice.max = prices[1];
}
}
} else if (k === 'color') {
const colorFind = _.find(filter.color, c => c.color_id === _.parseInt(params.color));
if (colorFind) {
condition.name = colorFind.color_name;
condition.color = colorFind.color_value ? 'url(' + colorFind.color_value.replace('http://', '//') + ')' : '#' + colorFind.color_code.replace('#', '');
}
} else if (k === 'size') {
const sizeFind = _.find(filter.size, c => c.size_id === _.parseInt(params.size));
if (sizeFind) {
condition.name = sizeFind.size_name;
}
} else if (k === 'age_level') {
if (filter.ageLevel.length > 1) {
const ageFind = _.find(filter.ageLevel, c => +c.id === _.parseInt(params.age_level));
if (ageFind) {
condition.name = ageFind.name;
}
}
} else if (k === 'gender') {
const genderFind = _.find(this.handleFilterGender(), 'checked');
if (genderFind) {
condition.name = genderFind.name;
}
} else if (k === 'brand') {
let brandFinds;
if (filter.paramBrand) {
brandFinds = filter.paramBrand;
} else {
const brands = _.split(params.brand, ',');
brandFinds = _.filter(filter.brand, c => _.some(brands, id => _.parseInt(id) === c.id));
}
if (brandFinds.length) {
condition.totalName = _.join(_.map(brandFinds, brand => brand.brand_name), '、');
condition.name = brandFinds.length > 1 ?
(`${brandFinds[0].brand_name}${brandFinds[1].brand_name.substring(0, 3)}...`) :
condition.totalName;
}
} else if (k === 'style') {
const styleids = _.split(params.style, ',');
const styleFinds = _.filter(filter.style,
style => _.some(styleids, id => _.parseInt(id) === style.style_id));
if (styleFinds.length) {
condition.name = styleFinds.length >= 2 ?
(`${styleFinds[0].style_name}${styleFinds[1].style_name}`) :
styleFinds[0].style_name;
}
}
if (condition.name) {
const clearParams = Object.assign({}, params, { [k]: '' });
condition.itemType = k;
condition.href = handleFilterUrl(baseUrl, clearParams);
conditions.push(condition);
return;
}
if (k === 'standard') {
const standard = _.get(origin, 'standard', []);
const standardList = _.split(params.standard, ',');
_.each(standardList, standardstr => {
const standardids = _.split(standardstr, '_');
if (standardids.length === 2) {
const pStandar = _.find(standard, s => _.parseInt(s.standard_id) === _.parseInt(standardids[0])); // eslint-disable-line
if (pStandar) {
const cStandar = _.find(pStandar.sub,
s => _.parseInt(s.standard_id) === _.parseInt(standardids[1]));
if (cStandar) {
const clearParams = Object.assign({}, params, { [k]: '' });
conditions.push({
itemType: pStandar.standard_name,
href: handleFilterUrl(baseUrl, clearParams,
{standard: _.join(_.filter(standardList, ids => ids !== standardstr), ',')}), // eslint-disable-line
name: cStandar.standard_name
});
}
}
}
});
}
});
return {conditions, customPrice};
}
handleFilterGender() { // 组装gender筛选数据
let {baseUrl, params} = this;
const href = handleFilterUrl(baseUrl, params, {gender: '${gender}'});
return [{
name: 'BOYS',
href: href.replace('${gender}', '1,3'),
checked: params.gender === '1,3'
}, {
name: 'GIRLS',
href: href.replace('${gender}', '2,3'),
checked: params.gender === '2,3'
}];
}
handleFilterBrand() { // 组装brand筛选数据
let {baseUrl, origin, params} = this;
const filter = _.get(origin, 'filter', {});
if (!filter.brand || !filter.brand.length) {
return false;
}
const brands = [];
const href = handleFilterUrl(baseUrl, params, {brand: '${brand}'});
const brandids = _.split(params.brand, ',');
_.each(filter.brand, brand => {
brands.push({
name: brand.brand_name,
href: href.replace('${brand}', _.replace(brand.id, '-', '__')), // 替换全球购品牌id中-
checked: _.some(brandids, bid => _.parseInt(bid) === brand.id)
});
if (brands.length >= 10) {
return false;
}
});
return {
default: brands,
showMore: brands.length > 9,
showMulti: brands.length > 9,
seatUrl: handleFilterUrl(baseUrl, params, {brand: '{seat}'})
};
}
handleFilterSizes() { // 组装sizes筛选数据
let {baseUrl, origin, params} = this;
const filter = _.get(origin, 'filter', {});
const sizes = [];
const href = handleFilterUrl(baseUrl, params, {size: '${size}'});
if (!params.category_id) {
return sizes;
}
_.each(filter.size, size => {
sizes.push({
name: size.size_name,
href: href.replace('${size}', size.size_id),
checked: size.size_id === _.parseInt(params.size)
});
});
return sizes;
}
handleFilterColors() {
let {baseUrl, origin, params} = this;
const filter = _.get(origin, 'filter', {});
const colors = [];
const href = handleFilterUrl(baseUrl, params, {color: '${color}'});
_.each(filter.color, color => {
colors.push({
name: color.color_name,
href: href.replace('${color}', color.color_id),
checked: color.color_id === _.parseInt(params.color),
rgb: color.color_value ?
'url(' + color.color_value.replace('http://', '//') + ')' :
'#' + color.color_code.replace('#', '')
});
});
return colors;
}
handleFilterAgeLevels() { // 组装ageLevels筛选数据
let {baseUrl, origin, params} = this;
const filter = _.get(origin, 'filter', {});
const ageLevels = [];
const href = handleFilterUrl(baseUrl, params, {age_level: '${age_level}'});
_.each(filter.ageLevel, age => {
ageLevels.push({
name: age.name,
href: href.replace('${age_level}', age.id),
checked: _.parseInt(age.id) === _.parseInt(params.age_level)
});
});
return ageLevels;
}
handleFilterPrices() { // 组装prices筛选数据
let {baseUrl, origin, params} = this;
const filter = _.get(origin, 'filter', {});
let prices = [];
const href = handleFilterUrl(baseUrl, params, {price: '${price}'});
_.each(filter.priceRange, (name, price) => {
prices.push({
name: name,
href: href.replace('${price}', price),
checked: price === params.price,
order: _.parseInt(_.split(price, ',')[0])
});
});
prices = _.sortBy(prices, (item) => {
return item.order;
});
return prices;
}
handleFilterStyles() { // 组装style筛选数据
let {baseUrl, origin, params} = this;
const filter = _.get(origin, 'filter', {});
let styles = [];
const href = handleFilterUrl(baseUrl, params, {style: '${style}'});
const styleids = _.split(params.style, ',');
_.each(filter.style, style => {
styles.push({
name: style.style_name,
href: href.replace('${style}', style.style_id),
checked: _.some(styleids, id => _.parseInt(id) === style.style_id),
id: style.style_id
});
});
return styles;
}
handleFilterStandars() { // 组装standars筛选数据
let {baseUrl, origin, params} = this;
const standards = _.get(origin, 'standard', {});
const filterStandars = [];
const standarParam = params.standard || '';
const href = handleFilterUrl(baseUrl, params, {standard: '${standard}'});
_.each(standards, standard => {
if (standard.sub.length > 1) {
filterStandars.push({
name: standard.standard_name,
sub: _.map(standard.sub, sub => {
return {
name: sub.standard_name,
href: href.replace('${standard}',
`${standarParam}${standarParam && ','}${standard.standard_id}_${sub.standard_id}`),
id: sub.standard_id
};
})
});
}
});
return filterStandars;
}
}
/**
* 处理筛选数据
* @param origin 要处理的筛选数据 filter
* @param params 当前 URL 中已有的参数,处理选中状态使用
* @returns {{}}
*/
const handleFilterData = (origin, params, baseUrl) => {
// 清除所有选中数据
// 某些特殊带频道信息页面,清除性别,需将gender设为1,2,3 (2017-3 配合SEO进行URL改造)
let remainParams = {
gender: '1,2,3'
};
const tools = new FilterTools(origin, params, baseUrl);
params.id && (remainParams.id = params.id);
params.union_type && (remainParams.union_type = params.union_type);
const clearUrl = handleFilterUrl(baseUrl, remainParams);
const {conditions, customPrice} = tools.handleFilterCheckedConditions();
const size = tools.handleFilterSizes();
const gender = tools.handleFilterGender();
const brand = tools.handleFilterBrand();
const color = tools.handleFilterColors();
const style = tools.handleFilterStyles();
const standard = tools.handleFilterStandars();
const checkedConditions = {
clearUrl,
conditions
};
let seniorChose = [];
let price = [];
let priceSeatUrl;
if (origin.total >= 10) {
price = tools.handleFilterPrices(origin, params);
priceSeatUrl = handleFilterUrl(baseUrl, params, {price: '{seat}'}); // 带[占位符]的前端跳转url
}
let ageLevel = tools.handleFilterAgeLevels(origin, params);
if (ageLevel.length <= 1) {
ageLevel = [];
}
if (style.length > 1) {
seniorChose.push({
name: '风格',
showMulti: true,
sub: style,
attr: 'style',
seatUrl: handleFilterUrl(baseUrl, params, {style: '{seat}'}) // 带[占位符]的前端跳转url
});
seniorChose = seniorChose.concat(standard);
}
return {
checkedConditions,
size,
gender,
brand,
color,
ageLevel,
customPrice,
price,
priceSeatUrl,
seniorChose
};
};
/**
* 处理 sort 排序数据
* @param params
* @param extra 什么都可以传进来,多个参数传Object
* @returns {{}}
*/
const handleOptSortData = (params, filter, baseUrl) => {
const href = handleFilterUrl(baseUrl, params, {order: '${order}'}, {page: true});
const sortType = [{
href: href.replace('${order}', ''),
name: '默认',
active: !params.order || params.order === 's_n_desc',
hasSortOrient: false
}, {
href: href.replace('${order}', 'h_v_desc'),
name: '人气',
active: params.order === 'h_v_desc',
hasSortOrient: false
}, {
href: params.order === 's_t_desc' ?
href.replace('${order}', 's_t_asc') :
href.replace('${order}', 's_t_desc'),
name: '新品',
active: params.order === 's_t_desc' || params.order === 's_t_asc',
hasSortOrient: true,
desc: params.order !== 's_t_desc'
}, {
href: params.order === 's_p_desc' ?
href.replace('${order}', 's_p_asc') :
href.replace('${order}', 's_p_desc'),
name: '价格',
active: params.order === 's_p_desc' || params.order === 's_p_asc',
hasSortOrient: true,
desc: params.order !== 's_p_desc'
}, {
href: params.order === 'p_d_desc' ?
href.replace('${order}', 'p_d_asc') :
href.replace('${order}', 'p_d_desc'),
name: '折扣',
active: params.order === 'p_d_desc' || params.order === 'p_d_asc',
hasSortOrient: true,
desc: params.order !== 'p_d_desc'
}];
const checks = [];
if (filter) {
if (filter.new || params.new === 'Y') {
checks.push({
name: '新品',
checked: params.new === 'Y',
href: handleFilterUrl(baseUrl, params, {new: 'Y'}, params.new === 'Y' ? {new: true} : {})
});
}
if (filter.specialoffer || params.specialoffer === 'Y') {
checks.push({
name: '打折',
checked: params.specialoffer === 'Y',
href: handleFilterUrl(baseUrl, params, {specialoffer: 'Y'}, params.specialoffer === 'Y' ? {specialoffer: true} : {}) // eslint-disable-line
});
}
if (filter.limited || params.limited === 'Y') {
checks.push({
name: '限量',
checked: params.limited === 'Y',
href: handleFilterUrl(baseUrl, params, {limited: 'Y'}, params.limited === 'Y' ? {limited: true} : {})
});
}
}
return {sortType, checks};
};
/**
* 处理 page 数据
* @param params
* @param extra 什么都可以传进来,多个参数传Object
* @returns {{}}
*/
const handlePageData = (params, total, baseUrl) => {
// 上下翻页数据处理
const pageSizeUrl = handleFilterUrl(baseUrl, params, {limit: '${limit}'}, {page: true});
const pageCounts = _.map(pageSizeType, size => {
return {
href: pageSizeUrl.replace('${limit}', size),
count: size
};
});
const curPage = _.parseInt(params.page || 1); // 当前页码数
const countPerPage = _.parseInt(params.limit || pageSizeType[0]) - 1; // 每页商品数量
const pageCount = _.ceil(total / countPerPage); // 全部页码数量
let preHref;
let nextHref;
const pageUrl = handleFilterUrl(baseUrl, params, {page: '${page}'});
if (curPage > 1) {
preHref = pageUrl.replace('${page}', curPage - 1);
}
if (curPage < pageCount) {
nextHref = pageUrl.replace('${page}', curPage + 1);
}
return {
pageCounts,
curPage,
countPerPage: countPerPage + 1,
pageCount,
preHref,
nextHref
};
};
/**
* 处理 opts 排序数据 new
* @param params
* @param extra 什么都可以传进来,多个参数传Object
* @returns {{}}
*/
const handleOptsData = (params, total, filter, baseUrl) => {
return Object.assign(
handleOptSortData(params, filter, baseUrl),
handlePageData(params, total, baseUrl));
};
/**
* 处理 下一页链接
* @param params
* @param extra 什么都可以传进来,多个参数传Object
* @returns {{}}
*/
const handleNextPage = (params, total, baseUrl) => {
let currentPage = parseInt((params.page ? params.page : 1), 10); // 当前页
let perPageCount = parseInt((params.limit ? params.limit : pageSizeType[0]) - 1, 10); // 每页商品数
let totalPage = _.ceil(total / perPageCount); // 总页数
if (currentPage >= totalPage) {
return null;
}
return {
href: handleFilterUrl(baseUrl, params, {page: currentPage + 1}),
src: '//img10.static.yhbimg.com/product/2014/01/15/11/01fa01614784f6239760f1b749663016f1.jpg?' +
'imageMogr2/thumbnail/235x314/extent/235x314/background/d2hpdGU=/position/center/quality/90'
};
};
/**
* 分页
* @param {[type]} total 总页数
* @param {[type]} params 筛选条件
* @param {[noNextBtn]} 列表是否有下一页的按钮,如果有则实际查询数比传递参数的少一个,入60 => 59
* @return {[type]} [description]
*/
const handlePagerData = (total, params, noNextBtn, baseUrl) => {
const curPage = _.parseInt(params.page || 1);
const pageSize = _.parseInt(params.limit || pageSizeType[0]) + (noNextBtn ? 0 : -1);
const totalPage = _.ceil(total / pageSize);
const tip = {
start: (curPage - 1) * pageSize + 1,
end: curPage * pageSize > total ? total : curPage * pageSize,
total
};
let prePage, nextPage;
const pageUrl = handleFilterUrl(baseUrl, params, {page: '${page}'});
if (curPage > 1) {
prePage = {
url: pageUrl.replace('${page}', curPage - 1)
};
}
if (curPage < totalPage) {
nextPage = {
url: pageUrl.replace('${page}', curPage + 1)
};
}
let pages = [];
let pagesNums = totalPage > 5 ? 5 : totalPage;
let offsetPage = curPage + _.round(0 - pagesNums / 2); // 遍历页码左侧数字
if (offsetPage <= 0) {
offsetPage = 1;
} else if (offsetPage + pagesNums > totalPage) {
offsetPage = totalPage - pagesNums + 1;
}
const preLimit = offsetPage - 1; // 页码1和遍历页码左侧的距离
const nextLimit = totalPage - (offsetPage - 1 + pagesNums); // 总页码和遍历页码右侧的距离
if (preLimit === 1) { // 如果左侧间距为1则显示这个页码
pagesNums++;
offsetPage--;
}
if (nextLimit === 1) { // 如果右侧间距为1则显示这个页码
pagesNums++;
}
if (preLimit >= 2) {
pages = _.concat(pages, {
num: 1,
url: pageUrl.replace('${page}', 1),
}, {
num: '...'
});
}
if (offsetPage <= 0) {
offsetPage = 1;
} else if (offsetPage + pagesNums > totalPage) {
offsetPage = totalPage - pagesNums + 1;
}
for (let i = 0; i < pagesNums; i++) {
pages.push({
num: offsetPage,
url: pageUrl.replace('${page}', offsetPage),
cur: curPage === offsetPage
});
offsetPage++;
}
if (nextLimit >= 2) {
pages = _.concat(pages, {
num: '...'
}, {
num: totalPage,
url: pageUrl.replace('${page}', totalPage),
});
}
return {tip, prePage, nextPage, pages};
};
module.exports = {
handlePathNavData,
handleSortData,
handleFilterData,
handleOptsData,
handleNextPage,
handlePagerData
};
... ...
... ... @@ -10,6 +10,7 @@ const ShopApiModel = require('./shop-api');
const headerModel = require('../../../doraemon/models/header');
const productProcess = require(`${utils}/product-process-simple`);
const searchHandler = require('./search-handler');
const listHandler = require('./list-handler');
const shopHandler = require('./shop-handler');
const helpers = global.yoho.helpers;
const crypto = global.yoho.crypto;
... ... @@ -19,6 +20,7 @@ const md5 = require('md5');
const cache = global.yoho.cache;
const config = global.yoho.config;
const logger = global.yoho.logger;
const redis = global.yoho.redis;
// const limitNum = 60; // 商品每页显示数目
const needParams = ['query', 'msort', 'misort', 'category_id', 'gender', 'shelveTime'];
... ... @@ -93,6 +95,8 @@ function getListData(params, channel) {
}
};
const baseUrl = '/list'; // 查询参数静态化base uri
// 获取左侧类目数据
if (result[1].code === 200) {
let dps = {};
... ... @@ -103,15 +107,14 @@ function getListData(params, channel) {
}
});
finalResult.list = Object.assign(
searchHandler.handlePathNavData(result[1].data, params, 'sort', channel), {
leftContent: searchHandler.handleSortData(result[1].data, dps, params)
});
finalResult.list = listHandler.handlePathNavData(result[1].data, params, 'sort', channel, baseUrl);
finalResult.list.leftContent = listHandler.handleSortData(result[1].data, dps, params, baseUrl);
}
// 获取商品数据和顶部筛选条件
if (result[2].code === 200) {
let filters = Object.assign(searchHandler.handleFilterDataAll(result[2].data, params),
let filters = Object.assign(listHandler.handleFilterData(result[2].data, params, baseUrl),
_.get(finalResult, 'list.leftContent.sort', {}));
filters.checkedConditions.conditions = _.concat(filters.checkedConditions.conditions,
... ... @@ -119,14 +122,14 @@ function getListData(params, channel) {
Object.assign(finalResult.list, {
filters: filters,
opts: searchHandler.handleOptsData(params, result[2].data.total, result[2].data.filter),
opts: listHandler.handleOptsData(params, result[2].data.total, result[2].data.filter, baseUrl),
totalCount: result[2].data.total,
footPager: searchHandler.handlePagerData(result[2].data.total, params),
footPager: listHandler.handlePagerData(result[2].data.total, params, false, baseUrl),
goods: productProcess.processProductList(result[2].data.product_list,
Object.assign({showDiscount: false}, params, {
from: {type: 'list', params: params}
})),
hasNextPage: searchHandler.handleNextPage(params, result[2].data.total),
hasNextPage: listHandler.handleNextPage(params, result[2].data.total, baseUrl),
// 最近浏览记录
latestWalk: 6
... ... @@ -147,58 +150,33 @@ function getListData(params, channel) {
_.get(finalResult, 'list.leftContent.allSort.list'),
_.get(finalResult, 'list.filters.checkedConditions.conditions'));
return Object.assign({}, seo, finalResult);
});
}
function getListDataPre(params, channel) {
let cKey = _getCacheKey(Object.assign({channel: channel}, params), 'list');
let getOriginData = () => {
return this.getListData(params, channel).then(result => {
// 查询结果为空则不cache
if (config.useCache && !_.isEmpty(_.get(result, 'list.goods', []))) {
cache.set(cKey, result, CACHE_TIME_S)
.catch(err => logger.debug(`list render cache data save fail:${err.toString()}`));
}
// 通过pathNav获取选中品类
let pathNav = _.get(finalResult, 'list.pathNav', []);
return result;
});
};
if (pathNav.length > 1) {
let sortName = _.last(pathNav).name;
if (config.useCache) {
return cache.get(cKey).catch(err => {
logger.debug(`get list render cache data fail:${err.toString()}`);
return redis.all([
['hmget', `category:description:${md5(sortName)}`, 'description']
]).then(desc => {
desc = _.get(desc, '[0][0]');
return getOriginData();
}).then(cdata => {
let hasCache = false;
if (cdata) {
try {
cdata = JSON.parse(cdata);
hasCache = true;
} catch (e) {
logger.debug('list render cache data parse fail.');
if (desc) {
_.set(finalResult, 'list.pageIntro', {title: sortName, intro: desc});
}
}
if (hasCache) {
return cdata;
} else {
return getOriginData();
}
});
}
return Object.assign({}, seo, finalResult);
});
}
return getOriginData();
return Object.assign({}, seo, finalResult);
});
}
/**
* 获取新品到着数据
*/
function getListNewData(params, channel) {
let searchParams = searchHandler.getSearchParams(params);
// 调用接口
... ... @@ -266,7 +244,8 @@ function getListNewData(params, channel) {
finalResult.criteo = {skn: searchHandler.getCriteo(_.get(finalResult.list, 'goods'))};
let seo = searchHandler.getNewSeo(channel, _.get(finalResult, 'list.leftContent.newSales.list'));
let seo = searchHandler.getNewSeo(channel,
params.category_id ? _.get(finalResult, 'list.leftContent.allSort.list') : null);
return Object.assign({}, seo, finalResult);
});
... ... @@ -546,7 +525,7 @@ function getShopAbout(shopId, uid, channel) {
Object.assign(decorator.shopTopBannerBase, {
shopId: shopId,
bannerHeight: 150,
shopHome: '?',
shopHome: `/shop/${_.get(result[2], 'data.shop_domain')}-${shopId}.html`,
shopIntro: `/shop${shopId}-about`,
coled: _.get(result, '[2].data.is_favorite', 'N') === 'Y'
});
... ... @@ -688,7 +667,6 @@ module.exports = class extends global.yoho.BaseModel {
this.shopApi = new ShopApiModel(ctx);
this.getListData = getListData.bind(this);
this.getListDataPre = getListDataPre.bind(this);
this.getListNewData = getListNewData.bind(this);
this.getListNewDataPre = getListNewDataPre.bind(this);
this.getBrandInfo = getBrandInfo.bind(this);
... ...
... ... @@ -61,7 +61,7 @@ const _proListHandler = (data, params) => {
_.forEach(pro.data, subData => {
tags.push({
url: helpers.urlFormat('', {sort: subData.relationParameter}, 'list'),
url: helpers.urlFormat('/list', {sort: subData.relationParameter}),
name: subData.categoryName,
cateId: subData.categoryId
});
... ...
... ... @@ -109,20 +109,23 @@ function getSaleGoodsData(params, vipLevel) {
case '5':
finalResult.goods.push({
thumb: '//cdn.yoho.cn/yohobuy-node/assets/img/sale/all-broken.jpg',
url: '/product/sale/breakingYards?channel=' + params.channel
url: '/product/sale/breakingYards?channel=' + params.channel,
noFollow: true
});
break;
case '2':
finalResult.goods.push({
thumb: '//cdn.yoho.cn/yohobuy-node/assets/img/sale/all-vip.jpg',
url: '/product/sale/vip?channel=' + params.channel,
vipPicture: true // 为了处理首页最后一张图片
vipPicture: true, // 为了处理首页最后一张图片
noFollow: true
});
break;
case '0':
finalResult.goods.push({
thumb: '//cdn.yoho.cn/yohobuy-node/assets/img/sale/all-sale.jpg',
url: '/product/sale/newSale?channel=' + params.channel
url: '/product/sale/newSale?channel=' + params.channel,
noFollow: true
});
break;
default:
... ... @@ -206,6 +209,7 @@ function getSaleIndexData(channel) {
);
}
let saleGoods = await Promise.all(_.cloneDeep(finalResult.saleCategory).map(value => {
return this.getSaleGoodsData(querystring.parse(_.trim(value.urlLocation, '?')));
}));
... ... @@ -329,6 +333,26 @@ function getSaleOthersData(params, channel) {
});
}
/**
* 设置折扣专场TDK
* @return {[object]} [tdk]
*/
function _setSaleDiscountData(info) {
let title = _.get(info, 'saleTitle.title', '');
let keyWordsArr = [title];
_.forEach(_.get(info, 'leftContent.allSort.list', []), value => {
keyWordsArr.push(`潮流折扣${value.name}`);
});
return {
title: `【${title}】潮流折扣商品|YOHO!BUY 有货`,
keywords: _.take(keyWordsArr, 5).join(','),
description: `有货网为您提供大量${title}商品,支持货到付款,质量保证,让您全面了解${title}商品价格、品牌、图片、折扣等方面信息,想网购${title}商品就上有货网!` // eslint-disable-line
};
}
/**
* 获取折扣专场数据 Controller 调用
* @return {[type]} [description]
... ... @@ -386,7 +410,6 @@ function getSaleDiscountData(params, channel) {
});
}
// 处理商品数据,顶部分类
if (subResult[1].code === 200) {
let sknArr = [];
... ... @@ -405,6 +428,8 @@ function getSaleDiscountData(params, channel) {
finalResult.criteo = {skn: sknArr}; // 重要:推广列表前三个商品Skn
}
finalResult.seo = _setSaleDiscountData(finalResult);
return finalResult;
});
}
... ... @@ -599,6 +624,15 @@ function getSaleSpecialData(id, params, channel) {
};
}
}
let specialName = _.get(special, 'data.special_name', '活动专区');
Object.assign(resData, {
title: `${specialName}|限时折扣|YOHO!BUY有货`,
keywords: `${specialName},限时折扣,折扣商品`,
description: `有货网为您带来限时${specialName},大量限时折扣商品,优惠幅度大,支持货到付款,让您全面了解限时${specialName}商品价格、品牌、图片、折扣等方面信息,想网购限时${specialName}商品就上有货网!` // eslint-disable-line
});
return resData;
});
});
... ...
... ... @@ -3,7 +3,6 @@
*/
'use strict';
const _ = require('lodash');
const Fn = require('lodash/fp');
const md5 = require('md5');
const config = global.yoho.config;
... ... @@ -22,13 +21,15 @@ const GLOBAL_BASE_URI = '/product/global/list';
// 缓存生效时间
const CACHE_TIME_S = 60;
const UNUSEDKEY = ['page', 'limit', 'need_filter', 'order'];
function getSearchCacheKey(params) {
let removeUnusedKey = Fn.omit(['page', 'limit', 'need_filter', 'order']);
let sortByKey = Fn.pipe(Fn.toPairs, Fn.sortBy(0), Fn.flatten);
let genKey = Fn.pipe(Fn.cloneDeep, removeUnusedKey, sortByKey, Fn.join('_'));
const paramList = Object.keys(params)
.filter(k => !_.some(UNUSEDKEY, key => key === k))
.sort();
const paramsStr = _.join(_.map(paramList, k => `${k}_${params[k] || ''}`), '_');
return 'search_custom_' + md5(genKey(params));
return 'search_custom_' + md5(paramsStr);
}
function _saveCache(key, kv, cacheTime) {
... ...
... ... @@ -1550,21 +1550,36 @@ exports.getListSeo = (channel, sorts, checked) => {
exports.getNewSeo = (channel, dlist) => {
let channelName = getChannelName(channel),
nlabel = '';
cateName = '';
_.forEach(dlist, d => {
if (d && d.active) {
nlabel = d.name || '';
return false;
}
});
if (!_.isEmpty(dlist)) {
_.forEach(dlist, cate => {
if (!cate.active) {
return;
}
let newTitle = channelName + nlabel;
cateName = cate.name;
_.forEach(cate.childList, (mcate, index) => {
if (index && mcate.childActive) {
cateName = mcate.name;
}
});
});
}
if (cateName) {
return {
title: `【${channelName}${cateName}】潮牌${cateName},最新${cateName}新品上架|YOHO!BUY 有货网!`,
keywords: `${channelName}${cateName},潮牌${cateName},新品${cateName}`,
description: `有货网为您提供最新的各种潮牌${channelName}${cateName},支持货到付款,让您全面了解最新潮牌${cateName}价格、品牌、图片等信息,想第一时间了解最新潮牌${cateName}就上有货网!` // eslint-disable-line
};
}
return {
title: newTitle + '新品上架-YOHO!BUY 有货 100%正品保证',
keywords: newTitle + '新品上架',
description: newTitle + '新品上架,正品网购,官方授权!YOHO! 有货中国最大的潮流商品购物网站。100%品牌正品保证,支持货到付款。'
title: `${channelName}新品上架,100%正品保证-YOHO!BUY 有货`,
keywords: `${channelName}新品,潮流新品,潮流正品`,
description: `${channelName}新品上架,正品网购,官方授权!100%品牌正品保证,支持货到付款。 想购买潮流商品就来YOHO! 有货中国最大的潮流商品购物网站。`
};
};
... ... @@ -1604,6 +1619,8 @@ exports.getBrandShopSeo = (channel, info, qs) => {
}
}
let description = `有货网${params.nameEn}旗舰店销售${params.name}正品商品,100%质量保证,支持货到付款,想了解${params.name}价格、图片、评价等信息,就上YOHO!BUY 有货中国最大的潮流商品购物网站!`; // eslint-disable-line
if (qs && qs.gender) {
if (qs.gender === '1,3') {
channel = 'boys';
... ... @@ -1612,21 +1629,18 @@ exports.getBrandShopSeo = (channel, info, qs) => {
}
Object.assign(params, ctype[channel] || ctype.boys);
Object.assign(resData, {
title: `${params.nameEn} | ${params.name} ${params.brandType}`,
title: `${params.nameEn} | ${params.name} ${params.brandType} | 正品保证, YOHO!BUY 有货`,
keywords: `${params.nameEn}, ${params.name} ${params.fashionType},${params.nameEn} ${params.brandType}`,
description: `${params.nameEn}正品网购。${params.name}官方授权!`
description: description
});
} else {
Object.assign(resData, {
title: `${params.nameEn} | ${params.name}旗舰店`,
keywords: `${params.nameEn}, ${params.name}旗舰店`,
description: `${params.nameEn}正品网购。${params.name}官方授权!`
title: `${params.nameEn} | ${params.name}品牌旗舰店 | 正品保证, YOHO!BUY 有货`,
keywords: `${params.nameEn}, ${params.name}品牌旗舰店,${params.name}正品`,
description: description
});
}
resData.title += resData.title ? ' | YOHO!BUY 有货 100%正品保证' : '';
resData.description += resData.description ? ' YOHO!BUY 有货中国最大的潮流商品购物网站。100%品牌正品保证,支持货到付款。' : ''; // eslint-disable-line
return resData;
};
... ...
... ... @@ -518,7 +518,7 @@ function getSearchKeywordDataById(id, params, channel) {
}
// 前10的热销品牌
Object.assign(resData.search.leftContent, searchHandler.hotBrands(hotBrandsModel.hotBrands()));
Object.assign(resData.search.leftContent, searchHandler.hotBrands(hotBrandsModel.hotBrands().slice(0, 10)));
return resData;
}).bind(this)();
... ...
... ... @@ -208,6 +208,8 @@ function _getBaseShopData(channel, params, shopInfo) {
let searchParams = searchHandler.getSearchParams(params);
let shopId = params.shopId;
delete params.shopId;
return co(function* () {
let result = yield Promise.props({
header: headerModel.requestHeaderData(channel), // 头部数据
... ... @@ -224,11 +226,17 @@ function _getBaseShopData(channel, params, shopInfo) {
}
const shopName = shopInfo.shop_name;
const shopAboutHref = `/shop${shopId}-about`;
let pageIntro = _.replace(shopInfo.shop_intro || '', /<\/?[^>]*>|\s*|(\n)|(\t)|(\r)/g, ''),
more = `... <a href="${shopAboutHref}" class="more-page-intro blue">了解更多>></a>`;
let resData = {
shopId: shopId,
brand: Object.assign({brandShopAd: true},
searchHandler.handlePathNavData({brandName: shopName}, params, 'shop', channel))
brand: Object.assign({
brandShopAd: true,
pageIntro: {title: shopName, intro: _.truncate(pageIntro, {length: 300, omission: more})}
}, searchHandler.handlePathNavData({brandName: shopName}, params, 'shop', channel)),
};
Object.assign(resData,
... ... @@ -239,8 +247,8 @@ function _getBaseShopData(channel, params, shopInfo) {
_.set(resData, 'brand.shopBanner', {
shopId: shopId,
shopName: shopName,
shopHome: '?',
shopIntro: `/shop${shopId}-about`
shopHome: `/shop/${shopInfo.shop_domain}-${shopId}.html`,
shopIntro: shopAboutHref
});
// 店铺装修
... ...
... ... @@ -10,6 +10,8 @@ const router = require('express').Router(); // eslint-disable-line
const cRoot = './controllers';
const auth = require(`${global.middleware}/auth`);
const gbk2utf = require(`${global.middleware}/gbk2utf`);
const paramParse = require(`${global.middleware}/param-parse`);
const sitemap = require('../3party/controllers/sitemap');
// 商品详情controller
... ... @@ -69,7 +71,9 @@ router.get('/outlets/list', outlets.list); // 奥莱品类页
router.get('/outlets/:channel', outlets.channel); // 奥莱频道页
// 商品详情
router.get('/list', outletsList.index);
router.get('/outletslist', outletsList.index);
router.get(/^\/([\d]+)(.*)/, detail.showMain); // 新的商品详情routers
router.get(/\/p([\d]+)(.*)/, detail.showMainBack); // 老的商品详情routers
... ... @@ -109,13 +113,15 @@ router.get('/search/less/recommend', search.searchLessRecommend);// 搜索少或
router.get('/search/keyword/:id', search.keyword);
router.get('/search/chanpin/:id', search.keyId);
// 商品分类列表页
router.get('/list/index', gbk2utf, list.index);
// 新品到着
router.get('/list/new', list.new);
router.get(/\/list\/(.*)-new/, list.newWithChannel);
// 商品分类列表页
router.get('/list', gbk2utf, list.index);
router.get('/list/index', gbk2utf, list.index);
router.get('/list/:pathQs', paramParse, list.index);
// 品牌店铺
router.get('/index/about', list.brandAbout); // 品牌店铺介绍页
router.post('/index/isFavoriteBrand', list.isFavoriteBrand); // 判断用户是否收藏品牌
... ...
... ... @@ -13,7 +13,7 @@
</div>
<div id="min-img">
<img id="img-show" class="img-show" src="{{image2 mainThumb w=420 h=560}}">
<img id="img-show" class="img-show" src="{{image2 mainThumb w=420 h=560}}" alt="{{productTitle}}">
<div class="magnifier move-object hide"></div>
<div class="magnifier move-over"></div>
<div id="max" class="magnifier max hide">
... ... @@ -32,14 +32,14 @@
{{# images_list}}
<img class="thumb {{#if @first}}active{{/if}}" src="{{image2 image_url w=75 h=100}}"
data-shower="{{image2 image_url w=420 h=560}}"
data-origin="{{image2 image_url w=750 h=1000}}">
data-origin="{{image2 image_url w=750 h=1000}}" alt="{{../../productTitle}}">
{{/ images_list}}
{{^}}
{{# images_list}}
<img class="thumb lazy"
data-original="{{image2 image_url w=75 h=100}}"
data-shower="{{image2 image_url w=420 h=560}}"
data-origin="{{image2 image_url w=750 h=1000}}">
data-origin="{{image2 image_url w=750 h=1000}}" alt="{{../../productTitle}}">
{{/ images_list}}
{{/if}}
</div>
... ... @@ -114,7 +114,7 @@
</div>
<div class="extra-tip">
<a href="/help/detail?id=39&contId=241">全球购物须知</a>
<a href="/help/detail?id=39&contId=241" rel="nofollow">全球购物须知</a>
<ul class="global-buy-tips">
{{# illustrate_contents}}
... ...
... ... @@ -109,6 +109,13 @@
{{> product/standard-content}}
{{# pageIntro}}
<div class="page-intro">
{{#if title}}<h1 class="page-title">{{title}}</h1>{{/if}}
{{{intro}}}
</div>
{{/ pageIntro}}
{{> product/recommend-keywords goodsInfo=@root.recommendKeywordsInfo}}
{{> product/latest-walk}}
... ...
... ... @@ -6,9 +6,9 @@
</div>
<div class="sale-group-big clearfix">
{{#big}}
<a class="item pull-left" href="{{link}}" target= "_blank">
<a class="item pull-left" href="{{link}}" target= "_blank" title="{{title}}">
<div class="pic">
<img src="{{image2 img w=375 h=375}}">
<img src="{{image2 img w=375 h=375}}" alt="{{title}}">
<div class="time"><span class="time-span"><span class="iconfont">&#xe60a;</span>{{time}}</span></div>
</div>
<div class="detail">
... ... @@ -29,8 +29,8 @@
</div>
<div class="sale-group clearfix">
{{#normal}}
<a class="item pull-left" href="{{link}}" target= "_blank">
<img class="pic" src="{{image2 img w=350 h=350}}">
<a class="item pull-left" href="{{link}}" target= "_blank" title="{{title}}">
<img class="pic" src="{{image2 img w=350 h=350}}" alt="{{title}}">
<div class="detail">
<div class="title">{{title}}</div>
<div class="time">{{time}}</div>
... ...
<div class="center-content clearfix">
{{#saleTitle}}
<div class="sale-title">
<span class="title">{{title}}</span>
<h1 class="title">{{title}}</h1>
{{#if discount}}
<span class="discount">{{discount}}</span>
{{/if}}
... ... @@ -27,4 +27,4 @@
{{/allSort}}
{{/leftContent}}
</ul>
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -16,8 +16,8 @@ module.exports = app => {
app.use(require('./apps/passport')); // 登录注册
app.use('/home', require('./apps/home')); // 会员中心
app.use(require('./apps/brands')); // 品牌一览
app.use('/guang/news', require('./apps/news')); // seo-潮流资讯页
app.use('/guang', require('./apps/guang')); // 逛
app.use('/news', require('./apps/news')); // seo-潮流资讯页
app.use('/cart', require('./apps/cart'));// 购物车
app.use('/help', require('./apps/help'));// 帮助中心
app.use('/shop', require('./apps/shop'));// 店铺
... ...
... ... @@ -60,7 +60,7 @@ exports.serverError = () => {
app: global.yoho.config.appName, // 应用名称
hostname,
type: 'server',
route: `[${req.method}]${req.route.path}`, // 请求路由
route: `[${req.method}]${req.route && req.route.path}`, // 请求路由
reqID: req.reqID,
uid,
udid,
... ...
/**
* 5cm.yohobuy.com 已经被百度收录,现在5cm店铺为 fivecentimeter,设置301到店铺,后期可删除本文件
* @author sefon 2017-05-04 11:18:56
*/
'use strict';
const TYPE = require('../type');
const helpers = global.yoho.helpers;
module.exports = [
{
type: TYPE.redirect,
origin: /.*/,
target: req => helpers.urlFormat(req.url, null, 'fivecentimeter')
}
];
... ... @@ -4,130 +4,132 @@
'use strict';
const _ = require('lodash');
const helpers = global.yoho.helpers;
const mapSort = require(`${global.utils}/map-sort`);
// const _ = require('lodash');
// const helpers = global.yoho.helpers;
// const mapSort = require(`${global.utils}/map-sort`);
const TYPE = require('../type');
module.exports = [
// 老版newURL
{
type: TYPE.redirect,
origin: '/new?gender=1,3&order=s_t_desc&msort=1,3,4,6,7,8,308,360',
target: helpers.urlFormat('/boys-new/', null, 'list')
},
{
type: TYPE.redirect,
origin: '/new?gender=2,3&order=s_t_desc&msort=1,3,4,6,7,8,308,360',
target: helpers.urlFormat('/girls-new/', null, 'list')
},
{
type: TYPE.redirect,
origin: '/new?order=s_t_desc&msort=365',
target: helpers.urlFormat('/kids-new/', null, 'list')
},
{
type: TYPE.redirect,
origin: '/new?order=s_t_desc&msort=10',
target: helpers.urlFormat('/lifestyle-new/', null, 'list')
},
// TODO: 暂时注释,上线一段时间正常即可删除
// // 老版newURL
// {
// type: TYPE.redirect,
// origin: '/new?gender=1,3&order=s_t_desc&msort=1,3,4,6,7,8,308,360',
// target: helpers.urlFormat('/boys-new/', null, 'list')
// },
// {
// type: TYPE.redirect,
// origin: '/new?gender=2,3&order=s_t_desc&msort=1,3,4,6,7,8,308,360',
// target: helpers.urlFormat('/girls-new/', null, 'list')
// },
// {
// type: TYPE.redirect,
// origin: '/new?order=s_t_desc&msort=365',
// target: helpers.urlFormat('/kids-new/', null, 'list')
// },
// {
// type: TYPE.redirect,
// origin: '/new?order=s_t_desc&msort=10',
// target: helpers.urlFormat('/lifestyle-new/', null, 'list')
// },
// 男生销售类目一级菜单
{
type: TYPE.redirect,
origin: '/?gender=1,3&msort=1,3',
target: helpers.urlFormat('/?category_id=5,8&gender=1,3', null, 'list')
},
{
type: TYPE.redirect,
origin: '/?gender=1,3&msort=6',
target: helpers.urlFormat('/?category_id=11&gender=1,3', null, 'list')
},
{
type: TYPE.redirect,
origin: '/?gender=1,3&msort=7',
target: helpers.urlFormat('/?category_id=14&gender=1,3', null, 'list')
},
{
type: TYPE.redirect,
origin: '/?gender=1,3&msort=8',
target: helpers.urlFormat('/?category_id=17&gender=1,3', null, 'list')
},
// // 男生销售类目一级菜单
// {
// type: TYPE.redirect,
// origin: '/?gender=1,3&msort=1,3',
// target: helpers.urlFormat('/?category_id=5,8&gender=1,3', null, 'list')
// },
// {
// type: TYPE.redirect,
// origin: '/?gender=1,3&msort=6',
// target: helpers.urlFormat('/?category_id=11&gender=1,3', null, 'list')
// },
// {
// type: TYPE.redirect,
// origin: '/?gender=1,3&msort=7',
// target: helpers.urlFormat('/?category_id=14&gender=1,3', null, 'list')
// },
// {
// type: TYPE.redirect,
// origin: '/?gender=1,3&msort=8',
// target: helpers.urlFormat('/?category_id=17&gender=1,3', null, 'list')
// },
// 女生销售类目一级菜单
{
type: TYPE.redirect,
origin: '/?gender=2,3&msort=1,3',
target: helpers.urlFormat('/?category_id=18,31,25&gender=2,3', null, 'list')
},
{
type: TYPE.redirect,
origin: '/?gender=2,3&msort=6',
target: helpers.urlFormat('/?category_id=52&gender=2,3', null, 'list')
},
{
type: TYPE.redirect,
origin: '/?gender=2,3&msort=7',
target: helpers.urlFormat('/?category_id=59&gender=2,3', null, 'list')
},
{
type: TYPE.redirect,
origin: '/?gender=2,3&msort=8,10,241',
target: helpers.urlFormat('/?category_id=76&gender=2,3', null, 'list')
},
// // 女生销售类目一级菜单
// {
// type: TYPE.redirect,
// origin: '/?gender=2,3&msort=1,3',
// target: helpers.urlFormat('/?category_id=18,31,25&gender=2,3', null, 'list')
// },
// {
// type: TYPE.redirect,
// origin: '/?gender=2,3&msort=6',
// target: helpers.urlFormat('/?category_id=52&gender=2,3', null, 'list')
// },
// {
// type: TYPE.redirect,
// origin: '/?gender=2,3&msort=7',
// target: helpers.urlFormat('/?category_id=59&gender=2,3', null, 'list')
// },
// {
// type: TYPE.redirect,
// origin: '/?gender=2,3&msort=8,10,241',
// target: helpers.urlFormat('/?category_id=76&gender=2,3', null, 'list')
// },
// 潮童销售类目一级菜单
{
type: TYPE.redirect,
origin: '/?gender=1,2,3&misort=382,368,372,448,392,388,384,414,429,390,425,464&msort=365',
target: helpers.urlFormat('/?category_id=13,16,15&gender=1,2,3', null, 'list')
},
// // 潮童销售类目一级菜单
// {
// type: TYPE.redirect,
// origin: '/?gender=1,2,3&misort=382,368,372,448,392,388,384,414,429,390,425,464&msort=365',
// target: helpers.urlFormat('/?category_id=13,16,15&gender=1,2,3', null, 'list')
// },
// 创意生活销售类目一级菜单
{
type: TYPE.redirect,
origin: '/?msort=10&misort=103',
target: helpers.urlFormat('/?category_id=21', null, 'list')
},
{
type: TYPE.redirect,
origin: '/?msort=10&misort=266',
target: helpers.urlFormat('/?category_id=20', null, 'list')
},
{
type: TYPE.redirect,
origin: '/?msort=10&misort=101,280',
target: helpers.urlFormat('/?category_id=251', null, 'list')
},
{
type: TYPE.redirect,
origin: '/?misort=259&msort=10',
target: helpers.urlFormat('/?category_id=23', null, 'list')
},
// // 创意生活销售类目一级菜单
// {
// type: TYPE.redirect,
// origin: '/?msort=10&misort=103',
// target: helpers.urlFormat('/?category_id=21', null, 'list')
// },
// {
// type: TYPE.redirect,
// origin: '/?msort=10&misort=266',
// target: helpers.urlFormat('/?category_id=20', null, 'list')
// },
// {
// type: TYPE.redirect,
// origin: '/?msort=10&misort=101,280',
// target: helpers.urlFormat('/?category_id=251', null, 'list')
// },
// {
// type: TYPE.redirect,
// origin: '/?misort=259&msort=10',
// target: helpers.urlFormat('/?category_id=23', null, 'list')
// },
// 筛选参数排序匹配
{
type: TYPE.redirect,
origin: req => {
if (_.isEmpty(req.query)) {
return false;
}
// // 筛选参数排序匹配
// {
// type: TYPE.redirect,
// origin: req => {
// if (_.isEmpty(req.query)) {
// return false;
// }
let sorts = mapSort(req.query);
let queryKeys = _.keys(req.query);
let index = 0;
let matched = _.map(sorts, (val, key) => {
return key === queryKeys[index++];
});
// let sorts = mapSort(req.query);
// let queryKeys = _.keys(req.query);
// let index = 0;
// let matched = _.map(sorts, (val, key) => {
// return key === queryKeys[index++];
// });
if (_.every(matched, match => match)) {
return false;
}
// if (_.every(matched, match => match)) {
// return false;
// }
return true;
},
target: req => helpers.urlFormat(req.path, mapSort(req.query), 'list')
},
// return true;
// },
// target: req => helpers.urlFormat(req.path, mapSort(req.query), 'list')
// },
{
type: TYPE.rewrite,
origin: req => {
... ...
... ... @@ -78,54 +78,6 @@ module.exports = [
target: (req, match, p1) => `/product/search/keyword/${p1}`
},
// TODO
// {
// type: TYPE.redirect,
// origin: /^\/so\/(.*)\.html(.*)/,
// target: (req, match, p1) => {
// let urls = {
// '4175746F426F74E6898BE69CBAE9858DE4BBB6E794B7': 57517,
// E6BBA1E58DB0E4BABAE5AD97E68B96: 11877,
// E6BDAEE6ACBEE5A4AAE79CBCE9959C: 43319,
// E6B3A2E782B9E995BFE8A296E8A1ACE8A1A3: 5709,
// E688B7E5A496E58C85E9858D: 27481,
// E993B6E98791E889B2: 12279,
// E697B6E5B09AE68ABDE7BBB3E79FADE8A3A4: 84593,
// '4C554E414C494D49544544E99288E7BB87E5A5B3': 36255,
// '4B4F594F': 10297,
// E99288E7BB87E8A5BFE8A385: 72093,
// E8838CE5BF83E995BFE8A399: 81419,
// E9929FE8A1A8E5A5B3: 71361,
// '424142414D41E79AAEE5B8A6': 47883,
// E5BEBDE7ABA0E58DABE8A1A3: 75023,
// E9BB91E799BDE6A0BC: 20095,
// E7949CE7BE8EE7BAAFE889B2E79FADE8A3A4: 10309,
// E58DB0E88AB1E995BFE6ACBEE7BEBDE7BB92E69C8D: 62085,
// E68B89E993BEE5BC80E8A59F: 43223,
// E7BBBFE889B2E7AE80E7BAA6E4BC91E997B2E8A3A4: 7781,
// E79CBCE5BDB1E5A5B3: 39279,
// E7BAAFE889B2E6A392E79083E5B8BD: 2021,
// E5A191E69699E590B8E7AEA1E69DAF: 1956427,
// E59BB4E5859C20E794B7: 71493,
// E59BB4E5859C20E5A5B3: 65257,
// E68BBCE889B2E6898BE993BE: 48821,
// '5452494E49544573747564696FE8A1ACE8A1AB': 53871,
// E799BDE889B2E9A490E585B7: 36291,
// E8939DE889B2E79CBCE9959C: 6287,
// E7AB96E69DA1E7BAB9E8BF9EE8A1A3E8A399: 40513,
// E7899BE4BB94E8939DE794B7E5A3ABE995BFE8A3A4: 2297,
// E58DB0E88AB1E4BC91E997B2E5A4B9E5858B: 26725,
// E8BF90E58AA8E8939DE78999E880B3E69CBA: 46837,
// E7BAAFE889B2E6B299E6BBA9E8A3A4: 8709,
// E7BAAFE889B2E8B4B4E6A087: 28027
// };
//
// return urls[p1] ?
// helpers.urlFormat(`/chanpin/${urls[p1]}.html`, null, 'www') :
// helpers.urlFormat('/', null, 'www');
// }
// },
// 推荐词id列表页
{
type: TYPE.rewrite,
... ... @@ -147,6 +99,15 @@ module.exports = [
target: helpers.urlFormat('/')
},
// 新品到着
{
type: TYPE.rewrite,
origin: /\/(.*)-new/,
target: (req, match, channel) => {
return `/product/list/${channel}-new`;
}
},
// 逛
// 首页
... ... @@ -206,6 +167,16 @@ module.exports = [
return `/guang/index/editor?channel=${channel}&author_id=${authorId}&page=${page}`;
}
},
// sale页
{
type: TYPE.rewrite,
origin: /^\/(boys|girls|kids|lifestyle)-sale(\/*)$/,
target: (req) => {
return `/product/${req.url}`;
}
},
{
type: TYPE.rewrite,
origin: /\/shop([\d]+)-about/,
... ...
... ... @@ -4,7 +4,6 @@
'use strict';
const _ = require('lodash');
const querystring = require('querystring');
const ptm = {
// 首页
... ... @@ -32,10 +31,7 @@ const ptm = {
module.exports = () => {
return (req, res, next) => {
let domain = 'm.yohobuy.com';
let proRegNew = /^\/product\/([\d]+).html(.*)/,
guangReg = /^\/guang/,
guangDetailReg = /\/guang\/info\/index/,
qsReg = /\?/;
let proRegNew = /^\/product\/([\d]+).html(.*)/;
if (!req.xhr) {
let url = _.head(_.split(req.url, '?'));
... ... @@ -49,22 +45,8 @@ module.exports = () => {
data.mobileRefer = `//${req.query.domain}.${domain}`;
} else if (url === '/product/search/index') {
data.mobileRefer = `//search.${domain}`;
} else if (guangReg.test(url)) {
data.mobileRefer = `//guang.${domain}`;
if (guangDetailReg.test(url)) {
data.mobileRefer += url.replace(/\/guang\/info\/index/, '/info/index');
} else if (url === '/guang/index/editor') {
data.mobileRefer += `/author-${req.yoho.channel}-${req.query.author_id}/`;
}
} else if (proRegNew.test(url)) {
data.mobileRefer = url.replace(proRegNew, `//${domain}/product/$1.html$2`);
} else {
data.mobileRefer = `//${domain}${req.originalUrl}`;
}
if (!_.isEmpty(req.query) && !qsReg.test(data.mobileRefer)) {
data.mobileRefer += `?${querystring.stringify(req.query)}`;
}
Object.assign(res.locals, data);
... ...
'use strict';
const parameter = require(`${global.utils}/parameter`);
module.exports = (req, res, next) => {
let param = req.params.pathQs;
if (param) {
Object.assign(req.query, parameter.minPathToFullParam(param));
}
next();
};
... ...
... ... @@ -27,26 +27,61 @@ const seoMap = {
keywords: '有货优惠券,有货现金优惠券,全场券,品类券,品牌券',
description: 'YOHO!BUY有货官网领券频道,提供有货优惠券,有货现金优惠券,有货全场券,有货品类券,品牌券免费领取,让你做网购达人,省钱又省心!'
},
'/boys-sale/': {
title: 'SALE|男装SALE,男装折扣|YOHO!BUY有货',
keywords: 'SALE,男装SALE,男装折扣',
description: 'YOHO!BUY有货SALE频道提供男装折扣,精致品牌男装sale,男装,针织衫,外套 卫衣,衬衫,T恤/POLO衫,裤子,品牌男鞋等限时特惠。YOHO!BUY有货男装折扣,100%正品保证!'
},
'/product/boys-sale/': {
title: 'SALE|男装SALE,男装折扣|YOHO!BUY有货',
keywords: 'SALE,男装SALE,男装折扣',
description: 'YOHO!BUY有货SALE频道提供男装折扣,精致品牌男装sale,男装,针织衫,外套 卫衣,衬衫,T恤/POLO衫,裤子,品牌男鞋等限时特惠。YOHO!BUY有货男装折扣,100%正品保证!'
},
'/girls-sale/': {
title: 'SALE|女装SALE,女装折扣|YOHO!BUY有货',
keywords: 'SALE,女装SALE,女装折扣',
description: 'YOHO!BUY有货SALE频道提供女装折扣,精致品牌女装sale,女装,针织衫,外套 卫衣,衬衫,T恤/POLO衫,裤子,品牌女鞋等限时特惠。YOHO!BUY有货女装折扣,100%正品保证!'
},
'/product/girls-sale/': {
title: 'SALE|女装SALE,女装折扣|YOHO!BUY有货',
keywords: 'SALE,女装SALE,女装折扣',
description: 'YOHO!BUY有货SALE频道提供女装折扣,精致品牌女装sale,女装,针织衫,外套 卫衣,衬衫,T恤/POLO衫,裤子,品牌女鞋等限时特惠。YOHO!BUY有货女装折扣,100%正品保证!'
},
'/kids-sale/': {
title: 'SALE|童装SALE,童装折扣,潮童鞋包配饰特卖|YOHO!BUY有货',
keywords: 'SALE,童装SALE,童装折扣,潮童鞋包配饰特卖',
description: 'YOHO!BUY有货SALE频道提供童装折扣,精致品牌童装sale,童装,针织衫,外套 卫衣,夹克,棉衣,裤子,品牌童鞋,潮童鞋包配饰等限时特惠。YOHO!BUY有货潮童折扣,100%正品保证!'
},
'/product/kids-sale/': {
title: 'SALE|童装SALE,童装折扣,潮童鞋包配饰特卖|YOHO!BUY有货',
keywords: 'SALE,童装SALE,童装折扣,潮童鞋包配饰特卖',
description: 'YOHO!BUY有货SALE频道提供童装折扣,精致品牌童装sale,童装,针织衫,外套 卫衣,夹克,棉衣,裤子,品牌童鞋,潮童鞋包配饰等限时特惠。YOHO!BUY有货潮童折扣,100%正品保证!'
},
'/lifestyle-sale/': {
title: 'SALE|家居生活用品SALE,生活用品折扣,数码家居特卖YOHO!BUY有货',
keywords: 'SALE,家居生活用品SALE,生活用品折扣,数码家居特卖',
description: 'YOHO!BUY有货SALE频道提供生活用品折扣,数码家居特卖,数码3c,居家,玩具娱乐,文具,美妆等限时特惠。YOHO!BUY有货家居生活用品SALE,,100%正品保证'
},
'/product/lifestyle-sale/': {
title: 'SALE|家居生活用品SALE,生活用品折扣,数码家居特卖YOHO!BUY有货',
keywords: 'SALE,家居生活用品SALE,生活用品折扣,数码家居特卖',
description: 'YOHO!BUY有货SALE频道提供生活用品折扣,数码家居特卖,数码3c,居家,玩具娱乐,文具,美妆等限时特惠。YOHO!BUY有货家居生活用品SALE,,100%正品保证'
},
'/product/sale/vip': {
title: 'VIP会员专享|会员专享|YOHO!BUY有货',
keywords: '会员专享,VIP专享,专享商品',
description: '有货网为您带VIP会员专享精选商品,大量潮流品牌商品,VIP价格优惠幅度大,支持货到付款,让您全面了解VIP会员专享商品价格、品牌、图片、折扣等方面信息,想网购VIP会员专享商品就上有货网!'
},
'/product/sale/breakingYards': {
title: '断码商品|断码折扣商品|YOHO!BUY有货',
keywords: '断码商品、断码专区、断码折扣',
description: '有货网为您带断码专区精选商品,大量断码商品,价格优惠幅度大,支持货到付款,让您全面了解潮流断码商品价格、品牌、图片、折扣等方面信息,想网购潮流断码区商品就上有货网!'
},
'/product/sale/newSale': {
title: '降价优选商品|潮流降价精品|YOHO!BUY有货',
keywords: '降价优选、降价商品,潮流商品',
description: '有货网为您带来降价优选商品,大量降价折扣优选商品,价格优惠幅度大,质量保证,支持货到付款,让您全面了解降价优选商品价格、品牌、图片、折扣等方面信息,想网购潮流降价商品就上有货网!'
},
'/privacy.html': {
title: `有货隐私条款|${siteName}`,
keywords: '有货隐私条款',
... ... @@ -71,6 +106,26 @@ const seoMap = {
title: `有货友情链接|${siteName}`,
keywords: '有货友情链接',
description: '有货友情链接,YOHO!BUY有货100%品牌正品保证,支持货到付款。'
},
'/cate': {
title: `【潮流品类大全】潮流正品|${siteName}`,
keywords: '潮流品类大全,潮流品类,有货网',
description: '有货网专业的潮流商品购物商城,提供各种潮流品牌,潮流品类以及全球最新最潮的潮流资讯,正品保障,货到付款。想要购买最新最潮的潮流商品,就上有货网!'
},
'/cate/': {
title: `【潮流品类大全】潮流正品|${siteName}`,
keywords: '潮流品类大全,潮流品类,有货网',
description: '有货网专业的潮流商品购物商城,提供各种潮流品牌,潮流品类以及全球最新最潮的潮流资讯,正品保障,货到付款。想要购买最新最潮的潮流商品,就上有货网!'
},
'/cpdq': {
title: `【产品大全】-${siteName}`,
keywords: '产品大全,产品分类,有货网',
description: '有货网专业的潮流商品购物商城,提供最全的潮流产品,正品保障,货到付款,想要购买最新的潮流产品,就上有货网!'
},
'/cpdq/': {
title: `【产品大全】-${siteName}`,
keywords: '产品大全,产品分类,有货网',
description: '有货网专业的潮流商品购物商城,提供最全的潮流产品,正品保障,货到付款,想要购买最新的潮流产品,就上有货网!'
}
/* eslint-enable */
... ...
... ... @@ -9,6 +9,7 @@
const uuid = require('uuid');
const _ = require('lodash');
const config = global.yoho.config;
const helpers = global.yoho.helpers;
const _getGender = (channel) => {
switch (channel) {
... ... @@ -92,6 +93,10 @@ module.exports = () => {
return udid;
}());
if (!req.xhr) {
yoho.mobileRefer = helpers.urlFormat(req.url, null, 'm');
}
Object.assign(res.locals, yoho);
Object.assign(req.yoho, yoho);
next();
... ...
... ... @@ -8,13 +8,15 @@
module.exports = () => {
return (req, res, next) => {
if (req.subdomains.length) {
let listReg = /^\/list(.*)$/;
switch (req.subdomains[0]) {
case 'www': // 主站
case 'cdnsrcwww': // 主站的回源地址
{ // eslint-disable-line
let shopReg = /^\/shop\/(.*)\.html(.*)$/;
if (shopReg.test(req.path)) {
if (shopReg.test(req.path) || listReg.test(req.path)) {
req.url = `/product${req.url}`;
}
... ... @@ -63,6 +65,8 @@ module.exports = () => {
req.url = '/product/list/index';
} else if (req.path === '/new') {
req.url = '/product/list/new';
} else if (listReg.test(req.path)) {
req.url = `/product${req.url}`;
}
break;
}
... ...
... ... @@ -226,8 +226,6 @@ const cacheHeaderHtml = {
lifestyle: []
};
let cacheNavData;
const THIRTY_MINUTES = 1000 * 60 * 10;
async function requestHeaderData(type) {
... ... @@ -265,8 +263,6 @@ async function requestHeaderData(type) {
if (res[0] && res[0].data) {
Object.assign(resData.headerData, setHeaderData(res[0].data, type));
cacheNavData = _.get(resData, 'headerData.subNavGroup', '');
} else {
logger.error('header api data empty');
}
... ... @@ -299,19 +295,6 @@ async function requestHeaderData(type) {
return Promise.resolve({headerData: _html});
}
async function getHeaderSubNav(type) {
if (_.isEmpty(cacheNavData)) {
let res = await getHeaderNavAsync();
cacheNavData = getSubNavGroup(res.data, type);
}
return Promise.resolve(_.find(cacheNavData, o => {
return o.subType === type;
}));
}
module.exports = {
requestHeaderData,
getHeaderSubNav
requestHeaderData
};
... ...
... ... @@ -5,6 +5,8 @@
*/
'use strict';
const helpers = global.yoho.helpers;
/**
* 热销品牌
*/
... ... @@ -13,54 +15,104 @@ const hotBrands = () => {
return [
{
url: '//www.yohobuy.com/shop/vans-1284.html',
url: helpers.urlFormat('/shop/vans-1284.html'),
image: `//img10.static.yhbimg.com/yhb-img01/2016/03/24/15/01ef24d3ec4caabd8c416901cdf4739917.jpg${imgView}`,
title: 'VANS/范斯'
},
{
url: '//www.yohobuy.com/shop/madness-1482.html',
url: helpers.urlFormat('/shop/madness-1482.html'),
image: `//img11.static.yhbimg.com/yhb-img01/2015/12/07/10/01e12663e56ae7c559ac72de209b6bf787.jpg${imgView}`,
title: 'MADNESS'
},
{
url: '//www.yohobuy.com/shop/hipanda-1488.html',
url: helpers.urlFormat('/shop/hipanda-1488.html'),
image: `//img11.static.yhbimg.com/yhb-img01/2017/11/06/09/01a9ea04b54af0c2830041678ff8e1b6a2.jpg${imgView}`,
title: 'HIPANDA/你好熊猫'
},
{
url: '//www.yohobuy.com/shop/dickies-1474.html',
url: helpers.urlFormat('/shop/dickies-1474.html'),
image: `//img10.static.yhbimg.com/yhb-img01/2017/11/03/11/018c06003f58b0a5087258ed21f63fde7b.jpg${imgView}`,
title: 'Dickies/迪凯斯'
},
{
url: '//www.yohobuy.com/shop/viishow-1360.html',
url: helpers.urlFormat('/shop/viishow-1360.html'),
image: `//img11.static.yhbimg.com/yhb-img01/2017/11/06/10/012ca25acd7958b8b499f80a40c28de059.jpg${imgView}`,
title: 'viishow/维秀'
},
{
url: '//www.yohobuy.com/shop/dusty-97.html',
url: helpers.urlFormat('/shop/dusty-97.html'),
image: `//img10.static.yhbimg.com/yhb-img01/2017/11/02/17/01eaa0d064e0a59ea683686637271eede0.jpg${imgView}`,
title: 'DUSTY/DUSTY潮牌'
},
{
url: '//www.yohobuy.com/shop/adidas-1258.html',
url: helpers.urlFormat('/shop/adidas-1258.html'),
image: `//img10.static.yhbimg.com/yhb-img01/2017/10/31/10/013ec61b8ccd4440db11c9ab2371c3605d.jpg${imgView}`,
title: 'adidas Originals/阿迪达斯'
},
{
url: '//www.yohobuy.com/shop/genanx-300.html',
url: helpers.urlFormat('/shop/genanx-300.html'),
image: `//img11.static.yhbimg.com/yhb-img01/2017/10/31/10/0183880efb53bb6e13fce74b670aef1cff.jpg${imgView}`,
title: 'Genanx/格男仕'
},
{
url: '//www.yohobuy.com/shop/glemall-2380.html',
url: helpers.urlFormat('/shop/glemall-2380.html'),
image: `//img10.static.yhbimg.com/yhb-img01/2017/11/03/09/0127a25d415d0e5a70fb26dc43ac1a5663.jpg${imgView}`,
title: 'GLEMALL'
},
{
url: '//www.yohobuy.com/shop/puma-1534.html',
url: helpers.urlFormat('/shop/puma-1534.html'),
image: `//img11.static.yhbimg.com/yhb-img01/2017/10/31/10/01e78f852cf69a57fefe71dcb8aab4b457.jpg${imgView}`,
title: 'PUMA/彪马'
},
{
url: helpers.urlFormat('/shop/thething-1330.html'),
image: `//img10.static.yhbimg.com/yhb-img01/2017/11/06/10/018cedbc8d32fb54edc54cc9e75c726464.jpg${imgView}`,
title: 'THETHING'
},
{
url: helpers.urlFormat('/shop/stussy-1292.html'),
image: `//img11.static.yhbimg.com/yhb-img01/2017/11/02/17/01f0487eefeecfc15ab3f8559317a8a3dc.jpg${imgView}`,
title: 'Stussy/斯图西'
},
{
url: helpers.urlFormat('/shop/converse-1252.html'),
image: `//img10.static.yhbimg.com/yhb-img01/2017/10/31/10/01b21a4da5297218adf33bedca11e09ce5.jpg${imgView}`,
title: 'Converse/匡威'
},
{
url: helpers.urlFormat('/shop/akop-2222.html'),
image: `//img11.static.yhbimg.com/yhb-img01/2017/11/03/09/0168a4088b1db414fac91286addb44fbe5.jpg${imgView}`,
title: 'AKOP'
},
{
url: helpers.urlFormat('/shop/timberland-2642.html'),
image: `//img10.static.yhbimg.com/yhb-img01/2017/11/06/10/017f4e8f44cf9f3f273d149ad57aa10257.jpg${imgView}`,
title: 'Timberland/添柏岚'
},
{
url: helpers.urlFormat('/shop/levis-1248.html'),
image: `//img11.static.yhbimg.com/yhb-img01/2017/11/06/09/011ead0b91f6f2cf776eb295555121e47e.jpg${imgView}`,
title: 'Levi’s/李维斯'
},
{
url: helpers.urlFormat('/shop/dc-275.html'),
image: `//img11.static.yhbimg.com/yhb-img01/2017/10/31/10/01f1bb407957dc717119ab9d32ea3f95fd.jpg${imgView}`,
title: 'DC/DCSHOECOUSA'
},
{
url: helpers.urlFormat('/shop/guuka-492.html'),
image: `//img11.static.yhbimg.com/yhb-img01/2017/11/02/17/01fcb145bf9e9276549468702b1ec57a7e.jpg${imgView}`,
title: 'Guuka/古由卡'
},
{
url: helpers.urlFormat('/shop/lal-1540.html'),
image: `//img10.static.yhbimg.com/yhb-img01/2017/11/02/16/013acf2a31ab930d34a80b2d87bfe4a9a9.jpg${imgView}`,
title: 'Life·After Life'
},
{
url: helpers.urlFormat('/shop/redcharcoal-2996.html'),
image: `//img10.static.yhbimg.com/yhb-img01/2017/10/31/10/01a8b7f3f496fbeb7a681aeacb9ea9aba5.jpg${imgView}`,
title: 'Red Charcoal'
}
];
};
... ...
... ... @@ -127,7 +127,7 @@
</div>
<div class="left">
<span class="iconfont rgbf">&#xe602;</span>
<a href="{{#if @root.pc.clientService.new}}http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409{{else}}//www.yohobuy.com/service/client{{/if}}" target="_blank">
<a href="{{#if @root.pc.clientService.new}}http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409{{else}}//www.yohobuy.com/service/client{{/if}}" target="_blank" rel="nofollow">
<span class="red">便捷</span>
<span class="rgbf">在线客服</span>
</a>
... ... @@ -282,7 +282,7 @@
<p class="links">
<a href="//www.yohobuy.com" rel="nofollow">返回首页</a>
<span>|</span>
<a href="//www.yohobuy.com/yohobuy.html">YOHO!BUY 有货</a>
<a href="//www.yohobuy.com/yohobuy.html" rel="nofollow">YOHO!BUY 有货</a>
<span>|</span>
<a href="//www.yohobuy.com/newpower.html" rel="nofollow">新力传媒</a>
<span>|</span>
... ... @@ -296,7 +296,11 @@
<span>|</span>
<a href="//www.yohobuy.com/brands">潮流品牌大全</a>
<span>|</span>
<a href="//www.yohobuy.com/news">潮流资讯</a>
<a href="//www.yohobuy.com/cate">潮流品类大全</a>
<span>|</span>
<a href="//www.yohobuy.com/cpdq">潮流产品大全</a>
<span>|</span>
<a href="//www.yohobuy.com/guang/news">潮流资讯</a>
<span>|</span>
<a href="//www.yohobuy.com/guang/boys-t2">穿衣搭配(男生版)</a>
<span>|</span>
... ... @@ -308,7 +312,7 @@
<span>|</span>
<a href="//www.yohobuy.com/guang/boys-t22">潮流视频</a>
<span>|</span>
<a class="police" target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=32010502010132">苏公网安备 32010502010132号</a>
<a class="police" target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=32010502010132" rel="nofollow">苏公网安备 32010502010132号</a>
</p>
</div>
<div class="copyright">
... ...
... ... @@ -17,7 +17,7 @@
</div>-->
<div class="left swindle-info">
<span class="icon-note"></span>
<a href="//www.yohobuy.com/help/detail?id=103&contId=147"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}} target="_blank">
<a href="//www.yohobuy.com/help/detail?id=103&contId=147" rel="nofollow" target="_blank">
关于防诈骗的重要提醒
</a>
</div>
... ... @@ -60,10 +60,10 @@
<a href="#">客户服务</a>
<ul class="nav-drop-down">
<li>
<a href="{{#if @root.pc.clientService.new}}http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409{{else}}//www.yohobuy.com/service/client{{/if}}"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}} target="_blank">在线客服</a>
<a href="{{#if @root.pc.clientService.new}}http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409{{else}}//www.yohobuy.com/service/client{{/if}}" rel="nofollow" target="_blank">在线客服</a>
</li>
<li>
<a href="//www.yohobuy.com/help"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>帮助中心</a>
<a href="//www.yohobuy.com/help" rel="nofollow">帮助中心</a>
</li>
</ul>
</li>
... ... @@ -80,7 +80,7 @@
<li class="phoneapp download-code" id="phoneApp">
<span class="tag-seprate"></span>
<span class="icon-phone"></span>
<a href="//www.yohobuy.com/download/app"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>手机版</a>
<a href="//www.yohobuy.com/download/app" rel="nofollow">手机版</a>
<div class="download-app-box">
<div class="qr-img code-img"></div>
<h5 class="qr-words">下载手机客户端</h5>
... ... @@ -101,13 +101,13 @@
{{# navbars}}
<li class="{{type}}">
{{#if ico}}
<a href="{{link}}"{{#if isNewPage}} target="_blank"{{/if}} class="menu-ico"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}></a>
<a href="{{link}}"{{#if isNewPage}} target="_blank"{{/if}} class="menu-ico"></a>
{{^}}
<h5 class="name-cn">
<a href="{{link}}"{{#if isNewPage}} target="_blank"{{/if}}{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>{{cn}}</a>
<a href="{{link}}"{{#if isNewPage}} target="_blank"{{/if}}>{{cn}}</a>
</h5>
<h5 class="name-en">
<a href="{{link}}"{{#if isNewPage}} target="_blank"{{/if}}{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>{{en}}</a>
<a href="{{link}}"{{#if isNewPage}} target="_blank"{{/if}}>{{en}}</a>
</h5>
{{/if}}
</li>
... ... @@ -128,7 +128,7 @@
{{#hotTerms}}
<li>
<a style="display: block;" href="{{href}}" title="{{content}}"
act="{{href}}"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}} target="_blank">
act="{{href}}" target="_blank">
<span class="searchvalue">{{content}}</span>
</a>
</li>
... ... @@ -137,7 +137,7 @@
</div>
<div class="go-cart">
<a href="//www.yohobuy.com/cart/cart">
<a href="//www.yohobuy.com/cart/cart" rel="nofollow">
<span class="iconfont ">&#xe600;</span>
{{#unless @root.pc.common.removeCartCount}}
<span class="goods-num-tip hide">0</span>
... ... @@ -168,6 +168,29 @@
<span class="newlogo"></span>
{{/if}}
</a>
{{#if thirdNav}}
<div class="third-nav-wrapper">
<div class="center-content">
<dl class="hide-list hide">
{{# thirdNav}}
<dt>
<h3 class=""><a href="{{link}}"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>{{title}}</a></h3>
</dt>
{{#brandItems}}
<dd>
<a href="{{link}}"{{#if hot}}
class="hot"{{/if}}{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>{{brandName}}</a>
</dd>
{{/brandItems}}
{{/thirdNav}}
</dl>
<div class="show-detail" data-code="{{imgCode}}">
<a{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}><img src="data:image/gif;base64,R0lGODlhAQABAJEAAAAAAP///93d3f///yH5BAEAAAMALAAAAAABAAEAAAICVAEAOw=="></a>
<a class="title">热门小物优选</a>
</div>
</div>
</div>
{{/if}}
</li>
{{/ subNav}}
</ul>
... ... @@ -267,4 +290,4 @@
<h5 class="code-title">下载手机客户端</h5>
<i class="iconfont icon-del"></i>
</div>
{{/ headerData}}
{{/ headerData}}
\ No newline at end of file
... ...
... ... @@ -98,7 +98,7 @@
{{/if}}
{{# brand}}
<div class="brand section" id="yo-filter-brands">
<div class="brand section" id="yo-filter-brands" data-url="{{seatUrl}}">
<span class="title">品牌:</span>
<div class="attr-content">
... ... @@ -164,7 +164,7 @@
<span class="price-sep">-</span>
<input type="text" class="max limit" value="{{customPrice.max}}">
<button class="price-sure hide">确定</button>
<button class="price-sure hide" data-url="{{priceSeatUrl}}">确定</button>
</div>
</div>
</div>
... ... @@ -244,7 +244,7 @@
<div class="senior-sub-wrap">
{{#each seniorChose}}
{{#if sub}}
<div class="senior-sub hide" data-attr="{{attr}}">
<div class="senior-sub hide" data-attr="{{attr}}" data-url="{{seatUrl}}">
<div class="senior-baffle"></div>
<div class="senior-content">
{{#if showMulti}}
... ...
... ... @@ -31,8 +31,8 @@
{{/ tags}}
</div>
<div class="good-detail-img">
<a class="good-thumb" href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image2 thumb w=280 h=382}}">
<a class="good-thumb" href="{{url}}" title="{{#if productTitle}}{{productTitle}}{{^}}{{product_name}}{{/if}}"{{#if noFollow}} rel="nofollow"{{/if}} target="_blank">
<img class="lazy" data-original="{{image2 thumb w=280 h=382}}" alt="{{#if productTitle}}{{productTitle}}{{^}}{{product_name}}{{/if}}">
</a>
{{# is_few}}
<p class="few-tag">即将售罄</p>
... ... @@ -43,9 +43,11 @@
{{/ is_solded}}
</div>
<div class="good-detail-text {{#for_stu}} stu-good-detail {{/for_stu}}">
<a href="{{url}}" target="_blank">{{{product_name}}}</a>
<a href="{{url}}" target="_blank"{{#if noFollow}} rel="nofollow"{{/if}}>{{{product_name}}}</a>
<p class="brand">
<a href="{{brandUrl}}"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>{{brand_name}}</a>
{{#if brand_name}}
<a href="{{brandUrl}}"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>{{brand_name}}</a>
{{/if}}
</p>
<p class="price {{#if vip}}vip-center{{/if}}">
{{# market_price}}
... ...
{{# recommendKeywords}}
<div class="recommend-keywords">
<h3>{{#if keywordsTitle}}{{keywordsTitle}}{{^}}相关推荐{{/if}}</h3>
<p>
{{# keywords}}
<a href="{{url}}" title="{{keyword}}" target="_blank" class="keyword">{{keyword}}</a>
{{/ keywords}}
</p>
</div>
{{/recommendKeywords}}
... ...
... ... @@ -54,7 +54,7 @@
<ul>
{{# pageCounts}}
<li>
<a href="{{href}}"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>{{count}}</a>
<a href="{{href}}" rel="nofollow">{{count}}</a>
</li>
{{/ pageCounts}}
</ul>
... ... @@ -62,7 +62,7 @@
<p class="page-orient">
{{#if preHref}}
<a href="{{preHref}}"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>
<a href="{{preHref}}" rel="nofollow">
<span class="iconfont">&#xe60e;</span>
</a>
{{^}}
... ... @@ -74,7 +74,7 @@
</span>
{{#if nextHref}}
<a href="{{nextHref}}"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>
<a href="{{nextHref}}" rel="nofollow">
<span class="iconfont">&#xe60c;</span>
</a>
{{^}}
... ... @@ -93,7 +93,7 @@
{{/each}}
{{# hasNextPage}}
<div class="block-next-page">
<a href="{{href}}"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>
<a href="{{href}}" rel="nofollow">
<img src="{{image2 src}}" alt=""/>
</a>
</div>
... ...
{{# subNav}}
<li {{#if thirdNav}}class="contain-third"{{/if}}>
<a href="{{link}}"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>{{name}}
{{#if isNew}}
<span class="newlogo"></span>
{{/if}}
</a>
{{#if thirdNav}}
<div class="third-nav-wrapper">
<div class="center-content">
<dl class="hide-list hide">
{{# thirdNav}}
<dt>
<h3 class=""><a href="{{link}}"{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>{{title}}</a></h3>
</dt>
{{#brandItems}}
<dd>
<a href="{{link}}"{{#if hot}}
class="hot"{{/if}}{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}>{{brandName}}</a>
</dd>
{{/brandItems}}
{{/thirdNav}}
</dl>
<div class="show-detail" data-code="{{imgCode}}">
<a{{#if @root.pageNoFollow}} rel="nofollow"{{/if}}><img src="data:image/gif;base64,R0lGODlhAQABAJEAAAAAAP///93d3f///yH5BAEAAAMALAAAAAABAAEAAAICVAEAOw=="></a>
<a class="title">热门小物优选</a>
</div>
</div>
</div>
{{/if}}
</li>
{{/ subNav}}
{
"name": "yohobuy-node",
"version": "6.1.16",
"version": "6.1.17",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ...
... ... @@ -3,7 +3,7 @@
{
"name": "yohobuy-node",
"script": "app.js",
"instances": "8",
"instances": "4",
"exec_mode": "cluster",
"merge_logs": true,
"log_date_format": "YYYY-MM-DD HH:mm Z",
... ...
... ... @@ -264,3 +264,7 @@ $('#comment-info').keyup(function() {
// init
$('#comment-info').trigger('keyup');
$(function() {
$('.guang-detail-page .article-main').find('a.a-anchor').attr({target: '_blank'});
});
... ...
... ... @@ -23,7 +23,7 @@ var $head = $('.head-wrapper'),
$miniCart = $head.find('.mini-cart-wrapper'),
$dropDown = $tool.find('.nav-drop-down-container');
var subNavFn;
var $subNav = $('.sub-nav-list.cure .contain-third');
var fetchUserInfoEvent = $.Callbacks('once'); // eslint-disable-line
... ... @@ -100,7 +100,6 @@ $('.we-chat').mouseenter(function() {
centerFn = handlebars.compile($('#simple-account-info-tpl').html() || '');
loginFn = handlebars.compile($('#header-login-info-tpl').html() || '');
cartFn = require('hbs/header/mini-cart-tpl.hbs'); // handlebars.compile($('#mini-cart-tpl').html() || '');
subNavFn = require('mix/common/header-nav.hbs');
// handlebars helper
handlebars.registerHelper('notzero', function(v1, options) {
... ... @@ -285,6 +284,32 @@ function getBannerAndNotice() {
});
}
// 格式化三级菜单
function formatThirdMenu() {
$subNav.each(function() {
var $thirdList = $(this).find('.hide-list'),
list = [],
i = 0;
if ($thirdList.length) {
$thirdList.children().each(function() {
if (i % thirdLineNum === 0) {
list.push('');
}
list[list.length - 1] += this.outerHTML + '';
i++;
});
for (i = 0; i < 3; i++) {
if (!list[i]) {
return;
}
$thirdList.before('<dl class="category-list">' + list[i] + '</dl>');
}
$thirdList.remove();
}
});
}
// 更新头部登陆信息
function updateLoginInfo(data) {
if (data.curLevel * 1 === 3) {
... ... @@ -565,134 +590,43 @@ function isSupportCss3Animation() {
}
}
if (isSupportCss3Animation()) {
requestFrame = requestFrameAct();
window.setTimeout(tsAnimate, 3000);
} else {
window.setTimeout(fadeAnimate, 3000);
}
// 菜单设置
(function() {
var headerNav = {
init: function() {
var that = this;
this.syncPageChannel();
this.$base = $('.sub-nav-list.cure');
$('.contain-third', this.$base).mouseenter(function() {
that.getThirdNavs();
});
},
syncPageChannel: function() {
var $header = $('#yoho-header'),
$navs;
var channel = window.homePage || window.cookie('_Channel') || 'boys',
qs = window.queryString();
channel = qs.channel ? qs.channel : channel;
// 处理pageCache频道显示异常问题
function syncPageChannel() {
var $header = $('#yoho-header'),
$navs;
var channel = window.homePage || window.cookie('_Channel') || 'boys',
qs = window.queryString();
if ($header && $header.length) {
$navs = $header.find('.' + channel);
channel = qs.channel ? qs.channel : channel;
if (!$navs.length) {
channel = 'boys';
$navs = $header.find('.' + channel);
}
// 更新频道菜单选中状态
$navs.siblings('.cure').removeClass('cure');
$navs.addClass('cure');
// 更新频道颜色
$header.addClass(channel).find('.func-area').removeClass('hide');
}
if ($header && $header.length) {
$navs = $header.find('.' + channel);
this.channel = channel;
},
getThirdNavs: function() {
var that = this;
if (!$navs.length) {
channel = 'boys';
$navs = $header.find('.' + channel);
}
if (this.loaded || this.loading) {
return;
}
// 更新频道菜单选中状态
$navs.siblings('.cure').removeClass('cure');
$navs.addClass('cure');
this.loading = true;
// 更新频道颜色
$header.addClass(channel).find('.func-area').removeClass('hide');
$.getJSON('//www.yohobuy.com/common/header/nav?callback=?', {channel: this.channel}, function(res) {
if (res.code === 200) {
that.loaded = true;
that.$base.html(subNavFn(res.data));
that.reseatThirdMenu();
}
that.loading = false;
});
},
reseatThirdMenu: function() {
$('.contain-third', this.$base).each(function() {
var $thirdList = $(this).find('.hide-list'),
list = [],
i = 0;
if ($thirdList.length) {
$thirdList.children().each(function() {
if (i % thirdLineNum === 0) {
list.push('');
}
list[list.length - 1] += this.outerHTML + '';
i++;
});
for (i = 0; i < 3; i++) {
if (!list[i]) {
return;
}
$thirdList.before('<dl class="category-list">' + list[i] + '</dl>');
}
$thirdList.remove();
}
}).on({
mouseenter: function() {
var $thirdNav = $(this).children('.third-nav-wrapper'),
$show = $thirdNav.find('.show-detail'),
param = {};
delayer = setTimeout(function() {
$thirdNav.show();
}, 200);
if (!$show.length || $show.hasClass('show')) {
return;
}
param.content_code = $show.data().code;
param.client_type = 'web';
param.width = 337;
param.height = 250;
param._ = new Date();
$.getJSON('//new.yohobuy.com/common/getbanner?callback=?', param, function(JsonData) {
if (JsonData.code === 200) {
$show.addClass('show');
$show.find('img').attr('src', JsonData.data.src);
$show.find('a').attr('href', JsonData.data.url);
$show.find('.title').text(JsonData.data.title);
}
});
},
mouseleave: function() {
var $thirdNav = $(this).children('.third-nav-wrapper');
if (delayer) {
clearTimeout(delayer);
}
$thirdNav.hide();
}
});
}
};
// 更新三级菜单jq对象
$subNav = $('.sub-nav-list.cure .contain-third');
}
}
headerNav.init();
}());
if (isSupportCss3Animation()) {
requestFrame = requestFrameAct();
window.setTimeout(tsAnimate, 3000);
} else {
window.setTimeout(fadeAnimate, 3000);
}
syncPageChannel();
formatThirdMenu(); // 格式化三级菜单
(function() {
if (document.all && !document.querySelector) {
... ... @@ -875,6 +809,43 @@ if ($miniCart && $miniCart.length) {
});
}
$subNav.on({
mouseenter: function() {
var $thirdNav = $(this).children('.third-nav-wrapper'),
$show = $thirdNav.find('.show-detail'),
param = {};
delayer = setTimeout(function() {
$thirdNav.show();
}, 200);
if (!$show.length || $show.hasClass('show')) {
return;
}
param.content_code = $show.data().code;
param.client_type = 'web';
param.width = 337;
param.height = 250;
param._ = new Date();
$.getJSON('//new.yohobuy.com/common/getbanner?callback=?', param, function(JsonData) {
if (JsonData.code === 200) {
$show.addClass('show');
$show.find('img').attr('src', JsonData.data.src);
$show.find('a').attr('href', JsonData.data.url);
$show.find('.title').text(JsonData.data.title);
}
});
},
mouseleave: function() {
var $thirdNav = $(this).children('.third-nav-wrapper');
if (delayer) {
clearTimeout(delayer);
}
$thirdNav.hide();
}
});
/**
* 首次进入有弹窗
* @return {[type]} [description]
... ...
var $ = require('yoho-jquery');
require('../common');
require('./img-blink');
require('./right-side');
$(function() {
$('.news-detail-page .article-main').find('a.a-anchor').attr({target: '_blank'});
});
... ...
... ... @@ -57,6 +57,8 @@ var sizeTmpl = '{{# size}}<a class="attr {{#if checked}}checked{{/if}}" href="{{
sizeCache = {}, // 缓存一下尺寸信息
$sizeWrap = $('.filter-box .size');
var staticPage = $('.yoho-page.static-list-page').length; // 是否是伪静态页面
if ($hideInfo && $hideInfo.length) {
hideInfo = $hideInfo.data();
$hideInfo.remove();
... ... @@ -91,16 +93,35 @@ function brandHideMore() {
}
// url构造&跳转
function uriLoc(attr, val) {
function uriLoc(attr, val, uri) {
var qs = window.queryString(),
newHref;
qs[attr] = val;
delete qs.page;
newHref = '?' + decodeURIComponent($.param(qs));
if (staticPage && uri) {
newHref = uri.replace('{seat}', (val + '').replace('-', '__'));
} else {
qs[attr] = val;
delete qs.page;
newHref = '?' + decodeURIComponent($.param(qs));
}
window.location.href = newHref;
}
function replceStaticUrl(list, uri) {
var i;
list = list || [];
if (staticPage && uri) {
for (i = 0; i < list.length; i++) {
list[i].href = uri.replace('{seat}', (list[i].id + '').replace('-', '__'));
}
}
return list;
}
// 隐藏高级选项面板
function hideSeniorPanel() {
$seniorSubWrap.children('.senior-sub:eq(' + hoveredIndex + ')').addClass('hide');
... ... @@ -185,6 +206,10 @@ function checkMoreBrands(callback) {
$brandsIndex = $('.brands-index');
}
if (staticPage) { // 伪静态化页面参数特殊处理
params = {pathname: window.location.pathname};
}
if (params.query && $changeKey.length) {
params.query = $changeKey.text();
}
... ... @@ -199,24 +224,32 @@ function checkMoreBrands(callback) {
moreBrandLoaded = 'loading';
$.getJSON(url, params, function(jsonData) {
var resData, seatUrl;
if (jsonData.code === 200) {
if (jsonData.code !== 200) {
return;
}
if (jsonData.data) {
brandsHtml = Handlebars.compile($('#yo-brands-tpl').html() || '');
$filterBrands.find('.attr-content [data-role=all-brand]').html(brandsHtml(jsonData.data));
}
resData = jsonData.data;
moreBrandLoaded = true;
if (resData) {
seatUrl = $filterBrands.data('url');
// init brand vars
$brandInput = $filterBrands.find('#brand-search-input');
$brandPanel = $filterBrands.find('.brand-panel');
$brandAttrs = $brandPanel.find('.attr');
$brandsIndex = $('.brands-index');
replceStaticUrl(resData.brandsShow, seatUrl);
return callback && callback();
brandsHtml = Handlebars.compile($('#yo-brands-tpl').html() || '');
$filterBrands.find('.attr-content [data-role=all-brand]').html(brandsHtml(resData));
}
moreBrandLoaded = true;
// init brand vars
$brandInput = $filterBrands.find('#brand-search-input');
$brandPanel = $filterBrands.find('.brand-panel');
$brandAttrs = $brandPanel.find('.attr');
$brandsIndex = $('.brands-index');
return callback && callback();
});
} else {
return callback && callback();
... ... @@ -312,7 +345,7 @@ $filterBrands.on('click', '#brand-multi-ok', function() {
val.push($(this).data('id'));
});
uriLoc('brand', val.join(','));
uriLoc('brand', val.join(','), $filterBrands.data('url'));
});
// 【品牌/高级选项】多选取消
... ... @@ -417,7 +450,7 @@ if ($udPrice.length > 0) {
min = tmp;
}
uriLoc('price', min + ',' + max);
uriLoc('price', min + ',' + max, $(this).data('url'));
});
}
... ... @@ -499,7 +532,7 @@ $('.senior-sub').on('click', '.multi-select', function() {
val.push($(this).data('id'));
});
uriLoc($sub.data('attr'), val.join(','));
uriLoc($sub.data('attr'), val.join(','), $sub.data('url'));
}).on('click', '.multi-select-cancel', function() {
var $panel = $(this).closest('.multi');
... ...
... ... @@ -172,6 +172,10 @@ function addCart() {
alert.show();
return;
}
alert = new Alert(data.message || '网络异常,请稍后再试');
alert.show();
return;
}
return $.Deferred().reject().promise(); // eslint-disable-line
... ...
.category-map-page {
.path-nav {
padding: 22px 0;
}
.list-block {
font-size: 12px;
border: 1px solid #dfdfdf;
margin-bottom: 30px;
.main-title {
line-height: 50px;
background-color: #eaeceb;
padding-left: 20px;
font-weight: bold;
}
> p {
display: block;
padding: 10px 0 10px 100px;
line-height: 30px;
border-top: 1px solid #dfdfdf;
position: relative;
box-sizing: border-box;
a {
margin-right: 20px;
}
}
.left-title {
position: absolute;
left: 20px;
font-weight: bold;
}
.channel-name {
padding-left: 0;
font-weight: bold;
text-align: center;
font-size: 14px;
}
}
.hot-brands {
width: 101%;
margin-bottom: 70px;
> a {
width: 116px;
height: 70px;
display: block;
padding: 10px 8px;
float: left;
box-sizing: border-box;
border: 1px solid #dfdfdf;
margin-left: -1px;
margin-top: -1px;
}
img {
width: 100%;
height: 100%;
display: block;
}
}
}
... ...
.chanpin-map-page {
.path-nav {
padding: 22px 0;
}
.chanpin-block {
font-size: 12px;
border: 1px solid #dfdfdf;
margin-bottom: 30px;
overflow: hidden;
.main-title {
line-height: 50px;
background-color: #eaeceb;
padding-left: 20px;
font-weight: bold;
}
}
.list-block {
width: 100.5%;
margin-bottom: -1px;
li {
width: 25%;
height: 50px;
line-height: 50px;
border: 1px solid #dfdfdf;
margin-left: -1px;
margin-top: -1px;
text-align: center;
float: left;
box-sizing: border-box;
}
a {
max-width: 90%;
line-height: 1.2;
color: #666;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
vertical-align: text-bottom;
}
}
.hot-brands {
width: 101%;
margin-bottom: 70px;
> a {
width: 116px;
height: 70px;
display: block;
padding: 10px 8px;
float: left;
box-sizing: border-box;
border: 1px solid #dfdfdf;
margin-left: -1px;
margin-top: -1px;
}
img {
width: 100%;
height: 100%;
display: block;
}
}
}
... ...
... ... @@ -4,3 +4,5 @@
@import "contact";
@import "link";
@import "privacy";
@import "category";
@import "chanpin";
... ...
... ... @@ -17,6 +17,7 @@
}
.text-info {
min-height: 400px;
padding: 20px;
color: #333;
overflow: hidden;
... ... @@ -29,11 +30,29 @@
font-size: 14px;
line-height: 30px;
border-bottom: 1px dashed #ccc;
font-weight: bold;
}
ul {
padding: 10px 0;
width: 710px;
padding: 20px 0;
list-style: none;
li {
width: 112px;
margin-right: 30px;
float: left;
display: block;
text-overflow: ellipsis;
white-space: nowrap;
}
img {
display: block;
width: 100%;
height: 40px;
margin-bottom: 14px;
}
}
strong {
... ...
... ... @@ -496,6 +496,12 @@
}
}
.plustar-title {
text-align: center;
line-height: 40px;
font-size: 20px;
}
.brands-items {
margin: 25px auto;
... ...
... ... @@ -15,6 +15,7 @@
overflow: hidden;
width: 100%;
height: 100%;
color: #fff;
}
.few-tag {
... ...
... ... @@ -64,6 +64,15 @@
width: 1150px;
margin: 0 auto;
.banner-img:before {
content: "";
width: 100%;
height: 100%;
background-image: resolve(product/banner-mark.png);
display: block;
opacity: 0.5;
}
.shop-name {
margin-left: 60px;
font-size: 32px;
... ... @@ -208,6 +217,10 @@
.brand-about {
font-size: 12px;
line-height: 150%;
img {
max-width: 100%;
}
}
.sort-intro {
... ... @@ -260,6 +273,24 @@
}
}
}
.page-intro {
margin-bottom: 20px;
line-height: 1.6;
color: #666;
font-size: 13px;
word-break: break-all;
.page-title {
font-size: 20px;
color: #444;
display: inline-block;
}
.blue {
color: #148bfa;
}
}
}
.min-screen .product-list-page .sort-intro {
... ...
... ... @@ -163,6 +163,7 @@
display: block;
width: 360px;
height: 240px;
color: #fff;
}
img.square {
... ...
... ... @@ -52,7 +52,7 @@
}
.detail-title {
font-size: 28px;
font-size: 26px;
line-height: 50px;
border-bottom: 1px dotted #c1c1c1;
word-wrap: break-word;
... ... @@ -99,6 +99,14 @@
}
}
.article-source {
float: left;
height: 64px;
line-height: 64px;
color: #999;
font-size: 13px;
}
.article-status {
float: right;
height: 64px;
... ... @@ -119,9 +127,11 @@
.article-main {
img {
display: block;
max-width: 100%;
margin: 0 auto;
height: auto;
width: auto;
max-width: 100%;
color: #fff;
}
.article-text {
... ... @@ -556,5 +566,10 @@
margin-bottom: 0;
}
}
.hot-brand {
width: 100%;
overflow: hidden;
}
}
... ...
@import "base";
@import "detail";
@import "recommend-keywords";
... ...
.recommend-keywords {
margin: 30px 0 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;
.keyword {
display: inline-block;
margin: 5px 15px;
font-size: 12px;
width: 150px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.common {
display: inline-block;
margin: 5px 15px;
font-size: 12px;
width: 190px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
... ...
... ... @@ -574,6 +574,8 @@
.title {
margin-right: 20px;
font-size: 16px;
display: inline-block;
vertical-align: middle;
}
.discount {
... ...
/**
* 静态化路由参数处理
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2017/11/24
*/
'use strict';
const _ = require('lodash');
// const logger = global.yoho.logger;
const queryString = require('querystring');
const minToFullMap = {
ag: 'age_level',
cn: 'channel',
gd: 'gender',
sn: 'sort_name',
pa: 'phrase',
ci: 'category_id',
so: 'sort',
ms: 'msort',
mi: 'misort',
tp: 'type',
sz: 'size',
cl: 'color',
pc: 'price',
bd: 'brand',
qr: 'query',
lt: 'limit',
ld: 'limited',
od: 'order',
nw: 'new',
pg: 'page',
st: 'style',
sd: 'standard',
si: 'specialsale_id',
sf: 'specialoffer'
};
const fullToMinMap = _.transform(minToFullMap, (result, value, key) => {
result[value] = key;
}, {});
const transformKey = (params, isFull) => {
if (_.isEmpty(params)) {
return params;
}
let matchParams = {},
extraParams = {};
let map = isFull ? fullToMinMap : minToFullMap;
_.forEach(params, (value, key) => {
let name = map[key];
if (name) {
matchParams[name] = value;
} else {
extraParams[key] = value;
// logger.info(`list parameter [${key}] map value not found`);
}
});
return {
matchParams,
extraParams
};
};
const minPathToFullParam = (path) => {
let obj = {};
_.forEach(_.split(path, '-'), splitValue => {
if (!splitValue) {
return;
}
let minKey = splitValue.substr(0, 2);
let fullKey = minToFullMap[minKey];
if (fullKey) {
obj[fullKey] = _.replace(_.replace(splitValue, minKey, ''), '__', '-'); // 替换value中__
}
});
return obj;
};
/**
* 筛选参数
* @param originParam 当前 URL 中的参数
* @param newParam 要拼接的 参数
* @returns {string}
*/
const fullParamToMinPath = (uri, params, newObj, delObj = {}) => {
let obj = _.assign({}, params, newObj);
let pathArr = [];
let extraQs = '';
Object.assign(delObj, {uid: true});
_.forEach(delObj, (value, key) => {
_.has(obj, key) && _.unset(obj, key);
});
let transParams = transformKey(obj, true);
_.forEach(transParams.matchParams, (value, key) => {
if (value) {
pathArr.push(`${key}${_.replace(value, '-', '__')}`); // 替换value中-
}
});
if (!_.isEmpty(transParams.extraParams)) {
extraQs = '?' + queryString.stringify(transParams.extraParams);
}
return _.trimEnd(uri, '/') + '/' + _.sortBy(pathArr).join('-') + extraQs;
};
module.exports = {
transformKey,
fullParamToMinPath,
minPathToFullParam
};
... ...
... ... @@ -3,6 +3,13 @@ const _ = require('lodash');
const helpers = global.yoho.helpers;
const logger = global.yoho.logger;
const genderName = {
1: '男生',
2: '女生',
'1,3': '男生',
'2,3': '女生'
};
/**
* 商品搜索商品数据处理
*/
... ... @@ -158,6 +165,9 @@ exports.processProductList = (list, options) => {
isfew ? proInfo.is_few = isfew : delete proInfo.is_few;
}
proInfo.productTitle = _.compact([product.brand_name_en, product.brand_name_cn || product.brand_name,
genderName[product.gender], product.small_sort_name, product.product_name]).join('|');
if (options.query && _.isString(proInfo.product_name)) {
try {
let qreg = new RegExp(options.query.replace('\\', '\\\\'), 'ig');
... ...
... ... @@ -103,6 +103,13 @@ const procProductImgs = (item, gender) => {
}
};
const genderName = {
1: '男生',
2: '女生',
'1,3': '男生',
'2,3': '女生'
};
/**
* 商品搜索商品数据处理
*/
... ... @@ -293,6 +300,10 @@ exports.processProductList = (list, options) => {
product.tags = tags;
isfew ? product.is_few = isfew : delete product.is_few;
}
product.productTitle = _.compact([product.brand_name_en, product.brand_name_cn || product.brand_name,
genderName[product.gender], product.small_sort_name, product.product_name]).join('|');
if (options.query && _.isString(product.product_name)) {
try {
let qreg = new RegExp(options.query.replace('\\', '\\\\'), 'ig');
... ...