Authored by yyq

Merge branch 'feature/product' of git.yoho.cn:fe/yoho-blk into feature/product

... ... @@ -3,7 +3,8 @@
const _ = require('lodash');
const Search = require('../models/search');
const camelCase = global.yoho.camelCase;
const DateHelper = require('../models/helpers');
const DataHelper = require('../models/helpers');
const Resouces = require('../models/resouces');
const list = {
index: (req, res, next) => {
... ... @@ -11,7 +12,7 @@ const list = {
q.page = q.page || 1;
let retDate = {
let retData = {
module: 'product',
page: 'list',
title: '列表'
... ... @@ -21,19 +22,25 @@ const list = {
if (result && result.code === 200 && result.data) {
let data = camelCase(result.data);
let nav = [DataHelper.getChannelNav()];
if (data.filter) {
retDate.filter = DateHelper.filterHandle(data.filter, q);
retData.filter = DataHelper.filterHandle(data.filter, q);
nav = _.concat(nav, retData.filter.nav);
}
retDate.paginationData = {
retData.navPath = {
nav: nav
};
retData.paginationData = {
page: q.page,
limit: data.limit || 45,
total: data.total,
pageTotal: data.pageTotal,
queryParams: q
};
res.display('list', _.assign(retDate, {
res.display('list', _.assign(retData, {
products: data.productList,
order: q.order
}));
... ... @@ -49,29 +56,40 @@ const list = {
q.page = q.page || 1;
let retDate = {
let retData = {
module: 'product',
page: 'list',
title: '列表'
};
Search.queryProduct(q).then(result => {
Promise.all([Resouces.newProductBanner(), Search.queryNewProduct(q)]).then(result => {
let banner = result[0];
let listData = result[1];
let nav = [DataHelper.getChannelNav(), {
name: '新品'
}];
if (result && result.code === 200 && result.data) {
let data = camelCase(result.data);
retData.banner = banner;
if (listData && listData.code === 200 && listData.data) {
let data = camelCase(listData.data);
if (data.filter) {
retDate.filter = DateHelper.filterHandle(data.filter, q);
retData.filter = DataHelper.filterHandle(data.filter, q);
}
retDate.paginationData = {
retData.navPath = {
nav: nav
};
retData.paginationData = {
page: q.page,
limit: data.limit || 45,
total: data.total,
pageTotal: data.pageTotal,
queryParams: q
};
res.display('newList', _.assign(retDate, {
res.display('newList', _.assign(retData, {
products: data.productList,
order: q.order
}));
... ... @@ -79,6 +97,7 @@ const list = {
return Promise.reject('query product error');
}
}).catch(next);
}
};
... ...
/**
* 搜索页
*
* @author: jiangfeng<jeff.jiang@yoho.cn>
* @date: 2016/7/12
*/
'use strict';
const _ = require('lodash');
const Search = require('../models/search');
const camelCase = global.yoho.camelCase;
const DataHelper = require('../models/helpers');
const Query = {
index: (req, res, next) => {
let q = req.query;
q.page = q.page || 1;
let retData = {
module: 'product',
page: 'list',
title: '列表'
};
Search.queryProduct(q).then(result => {
if (result && result.code === 200 && result.data) {
let data = camelCase(result.data);
let nav = [DataHelper.getChannelNav()];
nav.push({
name: `"${q.query}" ${data.total}个结果`
});
if (data.filter) {
retData.filter = DataHelper.filterHandle(data.filter, q);
}
retData.navPath = {
nav: nav
};
retData.paginationData = {
page: q.page,
limit: data.limit || 45,
total: data.total,
pageTotal: data.pageTotal,
queryParams: q
};
res.display('list', _.assign(retData, {
products: data.productList,
order: q.order
}));
} else {
return Promise.reject('query product error');
}
}).catch(next);
}
};
module.exports = Query;
... ...
... ... @@ -10,50 +10,64 @@
const _ = require('lodash');
const camelCase = global.yoho.camelCase;
// const cookie = global.yoho.cookie;
const BrandData = require('../models/brand-service');
const Search = require('../models/search');
const DateHelper = require('../models/helpers');
const DataHelper = require('../models/helpers');
function bannerFormat(banner) {
let url = banner.brandBanner;
return {
bgImg: banner.brandBanner,
bgImg: url.split('?')[0],
brandIntro: {
text: '品牌介绍'
},
height: 150
height: 150,
info: banner.brandIntro,
name: banner.brandName
};
}
function shopMenu() {
function shopMenu(domain) {
let menus = [
{name: '店铺首页', href: '/'},
{name: '全部商品', href: '/shop', icon: '&#xe60a;'},
{name: '人气单品', href: '/list?order=xxx'},
{name: '新品上架', href: '/list?order=s_t_desc'}
{name: '店铺首页', href: `/product/shop/${domain}`},
{name: '全部商品', href: `/product/shop/${domain}/list`, icon: '&#xe60a;'},
{name: '人气单品', href: `/product/shop/${domain}/list?order=xxx`},
{name: '新品上架', href: `/product/shop/${domain}/list?order=s_t_desc`}
];
return menus;
}
const shop = {
index(req, res) {
res.send('shop index');
},
list(req, res, next) {
let data = {
module: 'product',
page: 'shop-list',
title: '店铺列表'
};
let nav = [DataHelper.getChannelNav()];
let domain = req.params.domain;
// let uid = cookie.getUid(req);
let q = req.query;
q.page = q.page || 1;
data.shopMenu = shopMenu();
data.shopMenu = shopMenu(domain);
BrandData.getBrandByDomainAsync(domain).then(result => {
console.log(result);
data.brandBanner = bannerFormat(result);
q.brand = result.id;
q.shop_id = q.shopId || '';
nav.push({
name: result.brandName
});
}).then(() => {
return Search.queryProductOfBrand(q).then(result => {
... ... @@ -62,7 +76,7 @@ const shop = {
if (ret.filter) {
delete q.brand;
data.filter = DateHelper.filterHandle(ret.filter, req.query);
data.filter = DataHelper.filterHandle(ret.filter, req.query);
}
data.paginationData = {
... ... @@ -73,6 +87,10 @@ const shop = {
queryParams: req.query
};
data.navPath = {
nav: nav
};
res.display('shop-list', _.assign(data, {
products: ret.productList,
order: q.order
... ...
... ... @@ -51,12 +51,15 @@ const helpers = {
});
},
getNav(channel, sort, sorts) {
let nav = [{
getChannelNav() {
return {
link: '#',
pathTitle: '',
name: 'MEN首页'
}];
};
},
getSortNav(sort, sorts) {
let nav = [];
if (sort && sorts) {
sorts.forEach(s => {
... ... @@ -189,11 +192,9 @@ const helpers = {
filters: filters,
showFilters: filters.length > 0,
letters: this.brandLetters(),
navPath: {
nav: this.getNav('', q.sort, sorts)
},
customPriceLow: customPriceLow,
customPriceHigh: customPriceHigh
customPriceHigh: customPriceHigh,
nav: this.getSortNav(q.sort, sorts)
};
}
};
... ...
/**
* 资源位查询
*/
'use strict';
const api = global.yoho.ServiceAPI;
const logger = global.yoho.logger;
const Resources = {
/**
* 获取新品到着-列表页-banner 资源位
* @returns {Promise.<T>}
*/
newProductBanner() {
let params = {
content_code: 'a7989369aa86681c678bc40f171b8f1d'
};
return api.get('/operations/api/v5/resource/get', params).then(result => {
if (result && result.code === 200 && result.data) {
let data = result.data;
if (data.length > 0) {
let d = data[0].data;
return d ? d[0] : {};
}
}
return {};
}).catch(e => {
logger.error('get new product list banner error', e);
return {};
});
}
};
module.exports = Resources;
... ...
... ... @@ -17,9 +17,7 @@ const Search = {
let finalParams = {
method: 'app.search.li',
limit: 45,
productSize: '384x511',
yh_channel: 1
limit: 45
};
Object.assign(finalParams, clearEmptyVal(params));
... ... @@ -28,15 +26,28 @@ const Search = {
},
queryProductOfBrand(params) {
let finalParams = {
method: 'app.search.li',
limit: 45,
productSize: '384x511',
yh_channel: 1
method: 'app.search.brand',
limit: 45
};
Object.assign(finalParams, clearEmptyVal(params));
return api.get('', finalParams);
},
queryNewProduct(params) {
let finalParams = {
method: 'app.search.newProduct',
limit: 45
};
Object.assign(finalParams, clearEmptyVal(params));
return api.get('', finalParams);
},
queryAllSort() {
return api.get('', {
method: 'app.sort.get'
});
}
};
... ...
... ... @@ -11,6 +11,7 @@ const cRoot = './controllers';
const list = require(cRoot + '/list');
const item = require(cRoot + '/item');
const shop = require(cRoot + '/shop');
const query = require(cRoot + '/query');
// Your controller here
router.get('/list', list.index); // 列表页面
... ... @@ -18,6 +19,9 @@ router.get('/list/new', list.newPage); // 新品列表页
router.get(/\/item\/([\d]+)_([\d]+).html/, item.index); // 商品详情页
router.get('/shop/:domain', shop.list);
router.get('/shop/:domain/list', shop.list);
router.get('/shop/:domain', shop.index);
router.get('/query', query.index);
module.exports = router;
... ...
<div class="blk-page yoho-product-list">
<div class="center-content">
{{# filter.navPath}}
{{# navPath}}
{{> path-nav}}
{{/ filter.navPath}}
{{/ navPath}}
</div>
<div class="center-content clearfix">
<div class="left">
... ... @@ -24,4 +24,4 @@
{{{ pagination paginationData }}}
</div>
</div>
</div>
\ No newline at end of file
</div>
... ...
{{!-- 新品 列表页 --}}
<div class="blk-page yoho-product-list">
<div class="center-content">
{{# filter.navPath}}
{{# navPath}}
{{> path-nav}}
{{/ filter.navPath}}
{{/ navPath}}
</div>
<div class="center-content clearfix">
<div class="left">
... ... @@ -14,7 +14,9 @@
</div>
<div class="right">
{{!-- 新品banner --}}
<div class="banner-img" style="height: 200px;margin-bottom:30px; background:url(//img12.static.yhbimg.com/couponImg/2016/07/06/10/025f07ba2e91648de11e5c054471323920.jpg) no-repeat top center;"></div>
{{# banner}}
<div class="banner-img" style="height: 200px;margin-bottom:30px; background:url({{image src 850 200 2}}) no-repeat top center;"></div>
{{/banner}}
{{!-- 已选中条件 --}}
{{#filter}}
{{> list/filter-area}}
... ...
<div class="blk-page yoho-product-list">
<div class="center-content">
{{# filter.navPath}}
{{# navPath}}
{{> path-nav}}
{{/ filter.navPath}}
{{/ navPath}}
</div>
<div class="center-content clearfix">
{{> brand-banner-list }}
{{> list/shop-menu }}
{{> list/banner-info }}
</div>
<div class="center-content clearfix">
<div class="left">
... ...
{{# brandBanner}}
<div class="brand-banner" style="background-image: url('{{image bgImg 1150 150}}')">
<div class="brand-banner">
<div class="brand-img" style="height:150px; background: url('{{image bgImg 1150 150}}')"></div>
<p class="opts">
{{# brandIntro}}
<a href="{{link}}">
<a id="brand-info">
<i class="iconfont">&#xe631;</i>
{{text}}
</a>
... ...
{{# brandBanner}}
<div class="brand-info-wrapper">
<div class="brand-info">
<div class="nano-content">
<div class="brand-info-title">
<h2>{{name}}</h2>
<h5>品牌介绍</h5>
</div>
<div class="brand-info-content">
{{{info}}}
</div>
</div>
</div>
</div>
{{/brandBanner}}
... ...
... ... @@ -16,11 +16,11 @@
<div class="yoho-ui-accordion no-active">
{{#each sortData}}
<h3>{{categoryName}}</h3>
<div class="body" data-value="{{relationParameter.sort}}">
<div class="body" data-value="{{categoryId}}">
<div class="list-body nano">
<div class="nano-content">
{{#each sub}}
<div class="input-radio" data-value="{{relationParameter.sort}}">
<div class="input-radio" data-value="{{relationParameter.sort}}" data-category="{{categoryId}}">
{{> icon/radio }}
<label>{{categoryName}}</label>
</div>
... ... @@ -33,6 +33,7 @@
<div class="blank-div"></div>
{{#if brandData}}
<div class="yoho-ui-accordion">
<h3>品牌</h3>
<div class="body">
... ... @@ -68,6 +69,7 @@
</div>
</div>
</div>
{{/if}}
<div class="yoho-ui-accordion">
<h3>价格</h3>
... ...
... ... @@ -19,8 +19,8 @@ module.exports = {
},
cookieDomain: 'yohoblk.com',
domains: {
api: 'http://testapi.yoho.cn:28078/', // devapi.yoho.cn:58078 testapi.yoho.cn:28078 devapi.yoho.cn:58078
service: 'http://devservice.yoho.cn:28077/', // testservice.yoho.cn:28077 devservice.yoho.cn:58077
api: 'http://api.yoho.cn/', // devapi.yoho.cn:58078 testapi.yoho.cn:28078 devapi.yoho.cn:58078
service: 'http://service.yoho.cn/', // testservice.yoho.cn:28077 devservice.yoho.cn:58077
search: 'http://192.168.102.216:8080/yohosearch/'
},
useOneapm: false,
... ...
... ... @@ -14,6 +14,7 @@ var YohoListPage = {
require('yoho-jquery-accordion');
require('yoho-jquery-nanoscroller');
require('../../plugins/check');
require('../../common/return-top');
$('.nano').nanoScroller();
$('.yoho-ui-accordion', this.rootDoc).each(function() {
var opts = {
... ... @@ -41,7 +42,12 @@ var YohoListPage = {
type: 'radio',
group: 'sort',
onChange: function(ele, checked, value) {
var subCategoryId = $(ele).data('category');
var categoryId = $(ele).parents('.body').data('value');
YohoListPage.go({
categoryId: categoryId,
subCategoryId: subCategoryId,
sort: checked ? value : ''
});
}
... ... @@ -255,6 +261,9 @@ var YohoListPage = {
showGoodsWrapper: function(e) {
var position = $(e.currentTarget).position();
var productId = $(e.currentTarget).data('id');
var imgsSize = $(e.currentTarget).find('.goods-list i').length;
var cols = imgsSize % 4 === 0 ? imgsSize / 4 : (imgsSize / 4 + 1);
var imgsCol;
if (YohoListPage.goodsWrapperState && YohoListPage.productId !== productId) {
YohoListPage.goodsWrapperState = false;
... ... @@ -263,12 +272,25 @@ var YohoListPage = {
if (!YohoListPage.goodsWrapperState) {
YohoListPage.productId = productId;
position.top += 10;
if (position.left > 500) {
position.left -= cols * 60;
}
$(this.goodsWrapper).css(position);
$('.goods', this.goodsWrapper).html($(e.currentTarget).html());
$('.goods-img-list', this.goodsWrapper).empty();
$(e.currentTarget).find('.goods-list i').each(function() {
$('.goods-img-list', this.goodsWrapper).append(
$(e.currentTarget).find('.goods-list i').each(function(index) {
if (index % 4 === 0) {
imgsCol = document.createElement('div');
$(imgsCol).addClass('goods-img-col');
}
$(imgsCol).append(
'<img src="' + $(this).text() + '" width="60" height="80" alt="">');
if ((index + 1) % 4 === 0 || index === imgsSize - 1) {
$('.goods-img-list', YohoListPage.goodsWrapper).append(imgsCol);
imgsCol = null;
}
});
$(this.goodsWrapper).show();
YohoListPage.goodsWrapperState = true;
... ...
/**
* 店铺、品牌列表页
* @author: jiangfeng<jeff.jiang@yoho.cn>
*/
require('./list/list-search');
var Dialog = require('../plugins/dialog').Dialog;
var Shop = {
init: function() {
require('./list/list-search');
$('#brand-info').click(function() {
Shop.brandInfoDialog().show();
$('.brand-info').addClass('nano');
$('.brand-info').nanoScroller();
});
},
brandInfoDialog: function() {
var infoDaialog = new Dialog({
className: 'brand-info-dialog',
content: $('.brand-info-wrapper').html(),
keep: false
});
return infoDaialog;
}
};
Shop.init();
... ...
... ... @@ -36,6 +36,7 @@
bottom: 20px;
margin-left: 595px;
cursor: pointer;
z-index: 3;
.iconfont {
color: #fff;
... ...
... ... @@ -386,7 +386,7 @@
border: 2px solid #eae9e9;
position: absolute;
background: #fff;
z-index: 10;
z-index: 2;
top: 10px;
padding-right: 10px;
min-width: 383px;
... ... @@ -401,10 +401,16 @@
float: right;
margin: 2px 10px;
.goods-img-col {
display: inline-block;
vertical-align: top;
}
img {
margin: 8px 0;
cursor: pointer;
}
}
}
}
... ...
... ... @@ -45,4 +45,47 @@
}
}
}
.brand-info-wrapper {
display: none;
}
}
.yoho-dialog.brand-info-dialog {
width: 900px;
height: 600px;
.brand-info {
height: 520px;
width: 100%;
padding: 0 20px;
.nano-content {
width: 100%;
}
.brand-info-title {
text-align: left;
margin: 20px 0 50px;
h2 {
font-size: 18px;
font-weight: 700;
padding: 10px 0;
}
}
.brand-info-content {
p {
font-size: 12px;
line-height: 20px;
text-align: left;
img {
margin: 20px 0;
}
}
}
}
}
... ...