Authored by yyq

list seo

... ... @@ -32,7 +32,9 @@ exports.index = (req, res, next) => {
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] || {});
... ...
... ... @@ -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 = {
... ...
... ... @@ -7,7 +7,6 @@
'use strict';
const _ = require('lodash');
const helpers = global.yoho.helpers;
const queryString = require('querystring');
const indexUrl = {
boys: helpers.urlFormat('/'),
girls: helpers.urlFormat('/woman'),
... ... @@ -350,6 +349,7 @@ class FilterTools {
default: brands,
showMore: brands.length > 9,
showMulti: brands.length > 9,
seatUrl: handleFilterUrl(baseUrl, params, {brand: '{seat}'})
};
}
handleFilterSizes() { // 组装sizes筛选数据
... ... @@ -483,7 +483,7 @@ const handleFilterData = (origin, params, baseUrl) => {
params.id && (remainParams.id = params.id);
params.union_type && (remainParams.union_type = params.union_type);
const clearUrl = '?' + queryString.stringify(remainParams);
const clearUrl = handleFilterUrl(baseUrl, remainParams);
const {conditions, customPrice} = tools.handleFilterCheckedConditions();
const size = tools.handleFilterSizes();
... ... @@ -498,9 +498,11 @@ const handleFilterData = (origin, params, baseUrl) => {
};
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);
... ... @@ -513,7 +515,8 @@ const handleFilterData = (origin, params, baseUrl) => {
name: '风格',
showMulti: true,
sub: style,
attr: 'style'
attr: 'style',
seatUrl: handleFilterUrl(baseUrl, params, {style: '{seat}'}) // 带[占位符]的前端跳转url
});
seniorChose = seniorChose.concat(standard);
}
... ... @@ -527,6 +530,7 @@ const handleFilterData = (origin, params, baseUrl) => {
ageLevel,
customPrice,
price,
priceSeatUrl,
seniorChose
};
};
... ... @@ -650,6 +654,29 @@ const handleOptsData = (params, total, 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 总页数
... ... @@ -737,5 +764,6 @@ module.exports = {
handleSortData,
handleFilterData,
handleOptsData,
handleNextPage,
handlePagerData
};
... ...
... ... @@ -20,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'];
... ... @@ -128,7 +129,7 @@ function getListData(params, channel) {
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),
// 最近浏览记录
latestWalk: 6
... ... @@ -149,6 +150,21 @@ function getListData(params, channel) {
_.get(finalResult, 'list.leftContent.allSort.list'),
_.get(finalResult, 'list.filters.checkedConditions.conditions'));
// 通过pathNav获取选中品类
let pathNav = _.get(finalResult, 'list.pathNav', []);
if (pathNav.length > 1) {
let sortName = _.last(pathNav).name;
return redis.all([
['hmget', `category:description:${md5(sortName)}`, 'description']
]).then(descr => {
_.set(finalResult, 'list.pageIntro', `<em class="stage">${sortName}</em>${_.get(descr, '[0][0]')}`);
return Object.assign({}, seo, finalResult);
});
}
return Object.assign({}, seo, finalResult);
});
}
... ...
... ... @@ -71,7 +71,7 @@ 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
... ... @@ -118,6 +118,7 @@ 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);
... ...
... ... @@ -12,7 +12,7 @@ module.exports = () => {
case 'www': // 主站
case 'cdnsrcwww': // 主站的回源地址
{ // eslint-disable-line
let listReg = /^\/list\/(.*)$/;
let listReg = /^\/list(.*)$/;
let shopReg = /^\/shop\/(.*)\.html(.*)$/;
if (shopReg.test(req.path) || listReg.test(req.path)) {
... ...
... ... @@ -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}}
... ...
... ... @@ -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);
} 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);
}
}
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');
... ...
... ... @@ -275,6 +275,11 @@
line-height: 1.6;
color: #333;
font-size: 13px;
word-break: break-all;
.stage {
font-size: 20px;
}
.blue {
color: #148bfa;
... ...
... ... @@ -7,8 +7,10 @@
'use strict';
const _ = require('lodash');
const logger = global.yoho.logger;
const minToFullMap = {
ag: 'age_level',
gd: 'gender',
sn: 'sort_name',
pa: 'phrase',
... ... @@ -30,6 +32,7 @@ const minToFullMap = {
st: 'style',
sd: 'standard',
si: 'specialsale_id',
sf: 'specialoffer'
};
const fullToMinMap = _.transform(minToFullMap, (result, value, key) => {
... ... @@ -49,6 +52,8 @@ const transformKey = (params, isFull) => {
if (name) {
obj[name] = value;
} else {
logger.error(`list parameter [${key}] map value not found`);
}
});
... ... @@ -84,9 +89,6 @@ const fullParamToMinPath = (uri, params, newObj, delObj = {}) => {
let obj = _.assign({}, params, newObj);
let pathArr = [];
// console.log(obj);
//
Object.assign(delObj, {uid: true});
_.forEach(delObj, (value, key) => {
... ...