Authored by yyq

list path nav

... ... @@ -136,7 +136,7 @@ exports.article = (req, res, next) => {
let brands = req.query.brands;
if (!brands) {
return next();
return res.send('');
}
return req.ctx(shopModel).getShopArticleByBrandsAsync(brands).then(result => {
... ...
... ... @@ -23,7 +23,7 @@ const handleFilterUrl = require(`${global.utils}/parameter`).fullParamToMinPath;
const GlobalApiModel = require('./global-api');
const GLOBAL_LIST_URI = '/list/global';
const _handelGlobalPathNav = (data, channel, page) => {
const _handelGlobalPathNav = (data, channel, checked, page) => {
let rootName = '首页';
if (channel && _.isString(channel)) {
... ... @@ -42,7 +42,7 @@ const _handelGlobalPathNav = (data, channel, page) => {
if (data.sort) {
pathNav.push({
href: helpers.urlFormat(GLOBAL_LIST_URI, data.sort.params),
href: helpers.urlFormat(handleFilterUrl(GLOBAL_LIST_URI, data.sort.params)),
name: data.sort.name,
pathTitle: data.sort.name
});
... ... @@ -50,12 +50,24 @@ const _handelGlobalPathNav = (data, channel, page) => {
if (data.brand) {
pathNav.push({
href: helpers.urlFormat(handleFilterUrl(GLOBAL_LIST_URI, data.brand.params)),
name: data.brand.name,
pathTitle: data.brand.name
});
page = 'global-brand';
}
const kd = seoHandler.getSeoCheckedParamsName([], checked);
const lastName = `${kd.channel || ''}${kd.color || ''}${kd.size || ''}${_.get(data, 'sort.name') || ''}`; // eslint-disable-line
if (lastName) {
pathNav.push({
name: `${_.get(data, 'brand.name') || ''}${lastName}`
});
}
_.last(pathNav).useH1 = true;
return {
pathNav: pathNav,
listType: page
... ... @@ -77,7 +89,7 @@ const _checkSortEqual = (rp, params) => {
const _handelGlobalSort = (origin, params, originParams) => {
let all = [{
name: '全部品类',
href: `${handleFilterUrl(GLOBAL_LIST_URI, params, {}, {msort: true, misort: true, sort: true})}`
href: handleFilterUrl(GLOBAL_LIST_URI, params, {}, {msort: true, misort: true, sort: true})
}];
let list = [];
let selectSort = {};
... ... @@ -93,7 +105,7 @@ const _handelGlobalSort = (origin, params, originParams) => {
categoryId: value.category_id,
name: `全部${value.category_name}`,
num: value.node_count,
href: `${handleFilterUrl(GLOBAL_LIST_URI, params, value.relation_parameter)}`,
href: handleFilterUrl(GLOBAL_LIST_URI, params, value.relation_parameter),
childActive: _checkSortEqual(value.relation_parameter, originParams)
}
]
... ... @@ -116,7 +128,7 @@ const _handelGlobalSort = (origin, params, originParams) => {
categoryId: subValue.category_id,
name: subValue.category_name,
num: subValue.node_count,
href: `${handleFilterUrl(GLOBAL_LIST_URI, params, subValue.relation_parameter)}`,
href: handleFilterUrl(GLOBAL_LIST_URI, params, subValue.relation_parameter),
childActive: _checkSortEqual(subValue.relation_parameter, originParams)
};
... ... @@ -221,7 +233,8 @@ function getGlobalProductListData(params, yoho) {
if (brandName) {
pathInfo.brand = {
name: brandName
name: brandName,
params: {brand: _.get(result.brand, 'data.brand_id', '')}
};
// 添加品信息for seo
... ... @@ -239,7 +252,8 @@ function getGlobalProductListData(params, yoho) {
pathInfo.sort = selectedSort;
}
Object.assign(resData.list, _handelGlobalPathNav(pathInfo, yoho.channel, 'global-list'));
Object.assign(resData.list, _handelGlobalPathNav(pathInfo, yoho.channel,
_.get(resData, 'list.filters.checkedConditions.conditions'), 'global-list'));
let seo = seoHandler.getGlobalListSeo(_.get(resData, 'list.leftContent.allSort.list'),
fillCondition);
... ...
... ... @@ -14,9 +14,8 @@ const indexUrl = {
lifestyle: helpers.urlFormat('/lifestyle')
};
const parameter = require(`${global.utils}/parameter`);
const handleFilterUrl = parameter.fullParamToMinPath;
const handleFilterUrl = require(`${global.utils}/parameter`).fullParamToMinPath;
const seoHandler = require(`./seo-handler`);
// 页面商品数量
const pageSizeType = [40, 100, 200];
... ... @@ -140,6 +139,68 @@ const handlePathNavData = (data, params, page, channel, baseUrl) => {
};
/**
* 设置列表页相关页pathNav
* @type {[type]}
*/
const handleListPathNavData = (sorts, checked, params, channel, baseUrl) => {
let rootName = '首页';
channel = channel || 'boys';
if (channel && _.isString(channel)) {
rootName = channel.toUpperCase() + rootName;
}
let pathNav = [{
href: indexUrl[channel],
name: rootName, // '首页',
pathTitle: rootName, // '首页'
type: 'home'
}];
const kd = seoHandler.getSeoCheckedParamsName(sorts, checked);
// 无筛选参数时
if (_.isEmpty(kd)) {
return {pathNav};
}
const qs = {};
if (kd.sort) {
if (params.category_id) {
qs.category_id = params.category_id;
} else {
params.sort && (qs.sort = params.sort);
}
pathNav.push({
href: handleFilterUrl(baseUrl, qs),
name: kd.sort,
pathTitle: kd.sort,
type: 'sort'
});
}
if (params.brand && _.indexOf(params.brand, ',') < 0 && kd.brand) {
qs.brand = params.brand;
pathNav.push({
href: handleFilterUrl(baseUrl, qs),
name: kd.brand,
pathTitle: kd.brand,
type: 'brand'
});
}
pathNav.push({
name: `${kd.brand || ''}${kd.channel || ''}${kd.color || ''}${kd.size || ''}${kd.sort || ''}`,
useH1: true
});
return {pathNav};
};
/**
* 处理页面左侧分类筛选数据 new
* @param origin 分类原始数据,一般是接口返回数据中的 group_sort 字段
* @param params 当前 URL 中已有的参数
... ... @@ -865,6 +926,7 @@ const handleWeekNew = (data, params, baseUrl) => {
module.exports = {
handlePathNavData,
handleListPathNavData,
handleSortData,
handleFilterData,
handleOptsData,
... ...
... ... @@ -94,7 +94,7 @@ function getListData(params, channel) {
}
});
finalResult.list = listHandler.handlePathNavData(result[1].data, params, 'sort', channel, baseUrl);
// finalResult.list = listHandler.handlePathNavData(result[1].data, params, 'sort', channel, baseUrl);
finalResult.list.leftContent = listHandler.handleSortData(result[1].data, dps, params, baseUrl);
}
... ... @@ -133,37 +133,24 @@ function getListData(params, channel) {
Object.assign(finalResult.list.leftContent, searchHandler.handleSortAds(result[4].data));
}
let seo = searchHandler.getListSeo(channel,
_.get(finalResult, 'list.leftContent.allSort.list'),
_.get(finalResult, 'list.filters.checkedConditions.conditions'));
// 通过pathNav获取选中品类
let pathNav = _.get(finalResult, 'list.pathNav', []);
let checkedBrand = _.find(_.get(finalResult, 'list.filters.checkedConditions.conditions', []),
['itemType', 'brand']);
let shopUrl = _.get(finalResult, 'list.goods[0].brandUrl');
let sortName;
if (pathNav.length > 1) {
sortName = _.last(pathNav).name;
}
// 当选中品类且只选中一个品牌时导航栏展示品牌信息 for seo
if (shopUrl && !_.isEmpty(checkedBrand) && _.indexOf(checkedBrand.totalName, ',') === -1) {
pathNav.push({
href: shopUrl,
name: checkedBrand.totalName,
pathTitle: checkedBrand.totalName
});
if (sortName) {
pathNav.push({
href: `${shopUrl}?category_id=${params.category_id}`,
name: `${checkedBrand.totalName}${sortName}`,
pathTitle: `${checkedBrand.totalName}${sortName}`
});
const sortList = params.category_id ? _.get(finalResult, 'list.leftContent.allSort.list') : [];
const checkedList = _.get(finalResult, 'list.filters.checkedConditions.conditions');
// 面包屑导航
Object.assign(finalResult.list, listHandler.handleListPathNavData(sortList, checkedList,
params, channel, baseUrl));
_.map(finalResult.list.pathNav, nav => {
if (nav.type === 'brand') {
nav.href = _.get(finalResult, 'list.goods[0].brandUrl') || nav.href;
} else if (nav.type === 'sort') {
sortName = nav.name;
}
}
})
// seo
const seo = searchHandler.getListSeo(channel, sortList, checkedList);
if (sortName) {
return redis.all([
... ... @@ -173,13 +160,16 @@ function getListData(params, channel) {
if (desc) {
_.set(finalResult, 'list.pageIntro', {title: sortName, intro: desc});
// 有配置pageIntro时取消面包屑导航h1
_.last(finalResult.list.pathNav).useH1 = false;
}
return Object.assign({}, seo, finalResult);
});
}
return Object.assign({}, seo, finalResult);
return Object.assign(finalResult, seo);
});
}
... ... @@ -218,7 +208,6 @@ function getListNewData(params, channel) {
// 获取左侧类目数据
if (result[1].code === 200) {
finalResult.list = listHandler.handlePathNavData(result[1].data, params, 'new', channel, baseUrl);
finalResult.list.leftContent = listHandler.handleSortData(result[1].data, dps, params, baseUrl);
}
... ... @@ -254,12 +243,22 @@ function getListNewData(params, channel) {
finalResult.criteo = {skn: searchHandler.getCriteo(_.get(finalResult.list, 'goods'))};
let seo = searchHandler.getNewSeo(channel,
params.category_id ? _.get(finalResult, 'list.leftContent.allSort.list') : [],
_.get(finalResult, 'list.filters.checkedConditions.conditions'),
params.shelveTime);
const sortList = params.category_id ? _.get(finalResult, 'list.leftContent.allSort.list') : [];
const checkedList = _.get(finalResult, 'list.filters.checkedConditions.conditions');
return Object.assign({}, seo, finalResult);
Object.assign(finalResult.list, listHandler.handleListPathNavData(sortList, checkedList,
params, channel, baseUrl));
if (finalResult.list.pathNav && finalResult.list.pathNav.length < 2) { // 无参数添加新品到着
finalResult.list.pathNav.push({
name: '新品到着',
useH1: true
});
}
let seo = searchHandler.getNewSeo(channel, checkedList, checkedList, params.shelveTime);
return Object.assign(finalResult, seo);
});
}
... ...
... ... @@ -331,8 +331,22 @@ function getSaleOthersData(params, channel) {
}
}
finalResult.seo = seoHandler.getSaleListSeo(_.get(finalResult, 'leftContent.allSort.list'),
_.get(finalResult, 'filters.checkedConditions.conditions'),
const sortList = _.get(finalResult, 'leftContent.allSort.list');
const checkedList = _.get(finalResult, 'filters.checkedConditions.conditions');
Object.assign(finalResult, listHandler.handleListPathNavData(sortList, checkedList,
params, channel, baseUrl));
if (finalResult.pathNav) {
if (finalResult.pathNav.length < 2) { // 无参数添加店铺名
finalResult.pathNav.push({
name: params.saleType === '2' ? 'VIP会员' : '降价优选',
useH1: true
});
}
}
finalResult.seo = seoHandler.getSaleListSeo(sortList, checkedList,
params.saleType === '2' ? 'vip' : 'newSale');
return finalResult;
... ... @@ -530,10 +544,22 @@ function getSalebreakingYardsData(params, channel) {
});
}
finalResult.seo = seoHandler.getSaleListSeo(
_.get(finalResult, 'leftContent.allSort.list'),
_.get(finalResult, 'filters.checkedConditions.conditions'),
'breakingYards');
const sortList = _.get(finalResult, 'leftContent.allSort.list');
const checkedList = _.get(finalResult, 'filters.checkedConditions.conditions');
Object.assign(finalResult, listHandler.handleListPathNavData(sortList, checkedList,
params, channel, baseUrl));
if (finalResult.pathNav) {
if (finalResult.pathNav.length < 2) { // 无参数添加店铺名
finalResult.pathNav.push({
name: '断码特辑',
useH1: true
});
}
}
finalResult.seo = seoHandler.getSaleListSeo(sortList, checkedList, 'breakingYards');
return finalResult;
});
... ...
... ... @@ -6,7 +6,7 @@
const _ = require('lodash');
const _getSeoCheckedParamsName = (sorts, checked) => {
const getSeoCheckedParamsName = (sorts, checked) => {
let kd = {};
_.forEach(sorts, val => {
... ... @@ -73,7 +73,7 @@ const saleDefaultSeoMap = {
const getSaleListSeo = (sorts, checked, type) => {
const defaultTdk = saleDefaultSeoMap[type] || {};
const kd = _getSeoCheckedParamsName(sorts, checked);
const kd = getSeoCheckedParamsName(sorts, checked);
const typeNameMap = {
vip: 'VIP特惠',
... ... @@ -104,7 +104,7 @@ const getGlobalListSeo = (sorts, checked) => {
description: '全球购潮流服装配饰及创意生活正品网购!YOHO!BUY有货提供男生、女生、潮童服装配饰。100%品牌正品保证,支持货到付款。'
};
const kd = _getSeoCheckedParamsName(sorts, checked);
const kd = getSeoCheckedParamsName(sorts, checked);
// 无筛选参数时默认tdk
if (_.isEmpty(kd)) {
... ... @@ -152,7 +152,7 @@ const getShopHomeSeo = (shopInfo) => {
};
const getShopListSeo = (sorts, checked, shopInfo) => {
const kd = _getSeoCheckedParamsName(sorts, checked);
const kd = getSeoCheckedParamsName(sorts, checked);
const defaultTdk = getShopHomeSeo(shopInfo);
// 无筛选参数时返回空对象
... ... @@ -176,6 +176,7 @@ const getShopListSeo = (sorts, checked, shopInfo) => {
};
module.exports = {
getSeoCheckedParamsName,
getSaleListSeo,
getGlobalListSeo,
getShopHomeSeo,
... ...
... ... @@ -244,15 +244,14 @@ function _getBaseShopData(channel, params, shopInfo) {
let resData = {
shopId: shopId,
brand: Object.assign({
brand: {
brandShopAd: true,
pageIntro: {title: shopName, intro: _.truncate(pageIntro, {length: 300, omission: more})}
}, searchHandler.handlePathNavData({brandName: shopName}, params, 'shop', channel)),
}
};
Object.assign(resData, result.header);
// _.set(resData, 'headerData.header', true);
_.set(resData, 'brand.shopBanner', {
shopId: shopId,
shopName: shopName,
... ... @@ -322,8 +321,21 @@ function _getBaseShopData(channel, params, shopInfo) {
searchHandler.handleBrandShopCoupons(result.coupons.data, {shopId: shopId}));
}
Object.assign(resData, seoHandler.getShopListSeo(_.get(resData, 'brand.leftContent.allSort.list'),
_.get(resData, 'brand.filters.checkedConditions.conditions'), {shopName: shopName}));
const sortList = _.get(resData, 'brand.leftContent.allSort.list', []);
const checkedList = _.get(resData, 'brand.filters.checkedConditions.conditions');
Object.assign(resData.brand, listHandler.handleListPathNavData(sortList, checkedList,
params, channel, baseUrl));
if (resData.brand.pathNav) {
if (resData.brand.pathNav.length < 2) { // 无参数添加店铺名
resData.brand.pathNav.push({name: shopName});
} else { // 保留店铺介绍h1
_.last(resData.brand.pathNav).useH1 = false;
}
}
Object.assign(resData, seoHandler.getShopListSeo(sortList, checkedList, {shopName: shopName}));
return resData;
}).bind(this)();
... ... @@ -426,8 +438,6 @@ function _getShopListData(channel, params, shopInfo) {
let resData = {headerData: Object.assign(result.header.headerData, {header: true})};
let shopName = '';
Object.assign(resData, searchHandler.handlePathNavData({}, params, 'shop', channel));
// 店铺装修
if (result.decorator.code === 200) {
_.set(result, 'decorator.data.domain', _.get(result, 'shopInfo.data.shop_domain'));
... ... @@ -511,8 +521,21 @@ function _getShopListData(channel, params, shopInfo) {
}
}
Object.assign(resData, seoHandler.getShopListSeo(_.get(resData, 'leftContent.allSort.list'),
_.get(resData, 'filters.checkedConditions.conditions'), {shopName: shopName}));
const sortList = _.get(resData, 'leftContent.allSort.list', []);
const checkedList = _.get(resData, 'filters.checkedConditions.conditions');
Object.assign(resData, listHandler.handleListPathNavData(sortList, checkedList,
params, channel, baseUrl));
if (resData.pathNav && resData.pathNav.length < 2) { // 无参数添加店铺名
resData.pathNav.push({
name: shopName,
useH1: true
});
}
Object.assign(resData, seoHandler.getShopListSeo(sortList, checkedList, {shopName: shopName}));
resData.criteo = {skn: searchHandler.getCriteo(_.get(resData, 'goods'))};
... ...
... ... @@ -133,17 +133,19 @@ router.get('/index/about', list.brandAbout); // 品牌店铺介绍页
router.post('/index/isFavoriteBrand', list.isFavoriteBrand); // 判断用户是否收藏品牌
router.post('/index/getNodeContent', list.getNodeContent); // 品牌页水牌
router.post('/index/getAdnav', list.getAdnav); // 品牌页系列
router.get('/brand/couponsync', list.brandCouponSync);
router.get('/shop/couponsync', list.shopCouponSync);
router.get('/shop', shop.index); // 店铺首页
// router.get('/shop/:domain/:shopId.html', shop.index); // 店铺首页
router.get('/shop/:shopInfo.html', shop.index); // 店铺首页
router.get('/shop/:shopInfo', shop.list); // 店铺列表页
router.get('/shop/:shopInfo/:pathQs', paramParse, shop.list); // 店铺列表页
// router.get('/shoplist', shop.list); // 店铺列表页
router.get('/shop/article', shop.article); // 店铺推荐文章
router.post('/shop/article', shop.article); // 店铺推荐文章
router.post('/shop/togglecollect', favorite.collectShop); // 店铺收藏
router.post('/index/isFavoriteShop', favorite.isFavShop); // 判断用户是否收藏品牌
router.get('/brand/couponsync', list.brandCouponSync);
router.get('/shop/couponsync', list.shopCouponSync);
// 学生优惠routers
... ...
<div class="new-sale-page product-page yoho-page sale-discount-page {{pageClass}}">
{{# saleList}}
{{> common/path-nav}}
{{> sale/sale-banner}}
<div class="center-content clearfix">
{{# pathNav}}
{{> common/path-nav}}
{{/ pathNav}}
{{# saleTitle}}
<div class="header-title">
... ...
{{#if pathNav}}
<p class="path-nav" listType="{{listType}}" brandId="{{brandId}}">
<div class="path-nav" listType="{{listType}}" brandId="{{brandId}}">
{{#if isHelp}}
<span class="iconfont home-icon">&#xe61a;</span>
{{/if}}
{{#each pathNav}}
{{#if name}}
{{#if href}}
{{#if @last}}
<span class="last" title="{{pathTitle}}">{{{name}}}</span>
{{#if @last}}
{{#if useH1}}
<h1 class="last">{{{name}}}</h1>
{{^}}
<a href="{{href}}" title="{{pathTitle}}">{{{name}}}</a>
<span class="last">{{{name}}}</span>
{{/if}}
{{^}}
<span {{#if @last}}class="last"{{/if}} title="{{pathTitle}}">{{{name}}}</span>
{{#if href}}
<a href="{{href}}" title="{{pathTitle}}">{{{name}}}</a>
{{^}}
<span>{{{name}}}</span>
{{/if}}
{{/if}}
{{#unless last}}
{{#unless @last}}
<span class="iconfont">&#xe60c;</span>
{{/unless}}
{{#unless @last}}
<span class="iconfont">&#xe60c;</span>
{{/unless}}
{{/if}}
{{/each}}
</p>
</div>
{{/if}}
... ...
... ... @@ -209,7 +209,7 @@ $(window).on('scroll', function() {
if (brands) {
$.ajax({
type: 'GET',
type: 'POST',
url: '/product/shop/article',
data: {brands: brands}
}).then(function(data) {
... ...
... ... @@ -5,6 +5,11 @@
line-height: 18px;
color: #444;
> * {
font-size: 12px;
display: inline-block;
}
a {
color: #666;
}
... ...
.sale-discount-page {
> .path-nav {
width: 1150px;
margin: 0 auto;
}
.sale-list-banner {
width: 1150px;
position: relative;
... ...